Skip to content

Commit 08fd6b9

Browse files
author
Xavier Grangier
committed
grangier#188 - move meta extraction to MetasExtractor class
1 parent 8320262 commit 08fd6b9

3 files changed

Lines changed: 118 additions & 97 deletions

File tree

goose/crawler.py

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@
3535
from goose.extractors.tags import TagsExtractor
3636
from goose.extractors.opengraph import OpenGraphExtractor
3737
from goose.extractors.publishdate import PublishDateExtractor
38+
from goose.extractors.metas import MetasExtractor
3839
from goose.cleaners import StandardDocumentCleaner
3940
from goose.outputformatters import StandardOutputFormatter
4041

@@ -71,6 +72,9 @@ def __init__(self, config):
7172
# init the output formatter
7273
self.formatter = self.get_formatter()
7374

75+
# metas extractor
76+
self.metas_extractor = self.get_metas_extractor()
77+
7478
# publishdate extractor
7579
self.publishdate_extractor = self.get_publishdate_extractor()
7680

@@ -131,12 +135,15 @@ def crawl(self, crawl_candidate):
131135
# publishdate
132136
self.article.publish_date = self.publishdate_extractor.extract()
133137

134-
# self.article.additional_data = config.get_additionaldata_extractor.extract(doc)
135-
self.article.meta_lang = self.extractor.get_meta_lang()
136-
self.article.meta_favicon = self.extractor.get_favicon()
137-
self.article.meta_description = self.extractor.get_meta_description()
138-
self.article.meta_keywords = self.extractor.get_meta_keywords()
139-
self.article.canonical_link = self.extractor.get_canonical_link()
138+
# meta
139+
metas = self.metas_extractor.extract()
140+
self.article.meta_lang = metas['lang']
141+
self.article.meta_favicon = metas['favicon']
142+
self.article.meta_description = metas['description']
143+
self.article.meta_keywords = metas['keywords']
144+
self.article.canonical_link = metas['canonical']
145+
146+
# domain
140147
self.article.domain = self.extractor.get_domain()
141148

142149
# tags
@@ -214,6 +221,9 @@ def get_html(self, crawl_candidate, parsing_candidate):
214221
})
215222
return html
216223

224+
def get_metas_extractor(self):
225+
return MetasExtractor(self.config, self.article)
226+
217227
def get_publishdate_extractor(self):
218228
return PublishDateExtractor(self.config, self.article)
219229

goose/extractors/content.py

Lines changed: 0 additions & 89 deletions
Original file line numberDiff line numberDiff line change
@@ -20,14 +20,10 @@
2020
See the License for the specific language governing permissions and
2121
limitations under the License.
2222
"""
23-
import re
24-
2523
from copy import deepcopy
26-
from urlparse import urlparse, urljoin
2724

2825
from goose.extractors import BaseExtractor
2926

30-
RE_LANG = r'^[A-Za-z]{2}$'
3127

3228
KNOWN_ARTICLE_CONTENT_TAGS = [
3329
{'attr': 'itemprop', 'value': 'articleBody'},
@@ -50,91 +46,6 @@ def get_language(self):
5046
return self.article.meta_lang[:2]
5147
return self.config.target_language
5248

53-
def get_favicon(self):
54-
"""\
55-
Extract the favicon from a website
56-
http://en.wikipedia.org/wiki/Favicon
57-
<link rel="shortcut icon" type="image/png" href="favicon.png" />
58-
<link rel="icon" type="image/png" href="favicon.png" />
59-
"""
60-
kwargs = {'tag': 'link', 'attr': 'rel', 'value': 'icon'}
61-
meta = self.parser.getElementsByTag(self.article.doc, **kwargs)
62-
if meta:
63-
favicon = self.parser.getAttribute(meta[0], 'href')
64-
return favicon
65-
return ''
66-
67-
def get_meta_lang(self):
68-
"""\
69-
Extract content language from meta
70-
"""
71-
# we have a lang attribute in html
72-
attr = self.parser.getAttribute(self.article.doc, attr='lang')
73-
if attr is None:
74-
# look up for a Content-Language in meta
75-
items = [
76-
{'tag': 'meta', 'attr': 'http-equiv', 'value': 'content-language'},
77-
{'tag': 'meta', 'attr': 'name', 'value': 'lang'}
78-
]
79-
for item in items:
80-
meta = self.parser.getElementsByTag(self.article.doc, **item)
81-
if meta:
82-
attr = self.parser.getAttribute(meta[0], attr='content')
83-
break
84-
85-
if attr:
86-
value = attr[:2]
87-
if re.search(RE_LANG, value):
88-
return value.lower()
89-
90-
return None
91-
92-
def get_meta_content(self, doc, metaName):
93-
"""\
94-
Extract a given meta content form document
95-
"""
96-
meta = self.parser.css_select(doc, metaName)
97-
content = None
98-
99-
if meta is not None and len(meta) > 0:
100-
content = self.parser.getAttribute(meta[0], 'content')
101-
102-
if content:
103-
return content.strip()
104-
105-
return ''
106-
107-
def get_meta_description(self):
108-
"""\
109-
if the article has meta description set in the source, use that
110-
"""
111-
return self.get_meta_content(self.article.doc, "meta[name=description]")
112-
113-
def get_meta_keywords(self):
114-
"""\
115-
if the article has meta keywords set in the source, use that
116-
"""
117-
return self.get_meta_content(self.article.doc, "meta[name=keywords]")
118-
119-
def get_canonical_link(self):
120-
"""\
121-
if the article has meta canonical link set in the url
122-
"""
123-
if self.article.final_url:
124-
kwargs = {'tag': 'link', 'attr': 'rel', 'value': 'canonical'}
125-
meta = self.parser.getElementsByTag(self.article.doc, **kwargs)
126-
if meta is not None and len(meta) > 0:
127-
href = self.parser.getAttribute(meta[0], 'href')
128-
if href:
129-
href = href.strip()
130-
o = urlparse(href)
131-
if not o.hostname:
132-
z = urlparse(self.article.final_url)
133-
domain = '%s://%s' % (z.scheme, z.hostname)
134-
href = urljoin(domain, href)
135-
return href
136-
return self.article.final_url
137-
13849
def get_domain(self):
13950
if self.article.final_url:
14051
o = urlparse(self.article.final_url)

goose/extractors/meta.py

Lines changed: 102 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,108 @@
2121
limitations under the License.
2222
"""
2323

24+
import re
25+
from urlparse import urljoin
26+
from urlparse import urlparse
27+
2428
from goose.extractors import BaseExtractor
2529

2630

27-
class ContentMetaExtractor(BaseExtractor):
28-
pass
31+
RE_LANG = r'^[A-Za-z]{2}$'
32+
33+
34+
class MetasExtractor(BaseExtractor):
35+
36+
def get_favicon(self):
37+
"""\
38+
Extract the favicon from a website
39+
http://en.wikipedia.org/wiki/Favicon
40+
<link rel="shortcut icon" type="image/png" href="favicon.png" />
41+
<link rel="icon" type="image/png" href="favicon.png" />
42+
"""
43+
kwargs = {'tag': 'link', 'attr': 'rel', 'value': 'icon'}
44+
meta = self.parser.getElementsByTag(self.article.doc, **kwargs)
45+
if meta:
46+
favicon = self.parser.getAttribute(meta[0], 'href')
47+
return favicon
48+
return ''
49+
50+
def get_canonical_link(self):
51+
"""\
52+
if the article has meta canonical link set in the url
53+
"""
54+
if self.article.final_url:
55+
kwargs = {'tag': 'link', 'attr': 'rel', 'value': 'canonical'}
56+
meta = self.parser.getElementsByTag(self.article.doc, **kwargs)
57+
if meta is not None and len(meta) > 0:
58+
href = self.parser.getAttribute(meta[0], 'href')
59+
if href:
60+
href = href.strip()
61+
o = urlparse(href)
62+
if not o.hostname:
63+
z = urlparse(self.article.final_url)
64+
domain = '%s://%s' % (z.scheme, z.hostname)
65+
href = urljoin(domain, href)
66+
return href
67+
return self.article.final_url
68+
69+
def get_meta_lang(self):
70+
"""\
71+
Extract content language from meta
72+
"""
73+
# we have a lang attribute in html
74+
attr = self.parser.getAttribute(self.article.doc, attr='lang')
75+
if attr is None:
76+
# look up for a Content-Language in meta
77+
items = [
78+
{'tag': 'meta', 'attr': 'http-equiv', 'value': 'content-language'},
79+
{'tag': 'meta', 'attr': 'name', 'value': 'lang'}
80+
]
81+
for item in items:
82+
meta = self.parser.getElementsByTag(self.article.doc, **item)
83+
if meta:
84+
attr = self.parser.getAttribute(meta[0], attr='content')
85+
break
86+
87+
if attr:
88+
value = attr[:2]
89+
if re.search(RE_LANG, value):
90+
return value.lower()
91+
92+
return None
93+
94+
def get_meta_content(self, metaName):
95+
"""\
96+
Extract a given meta content form document
97+
"""
98+
meta = self.parser.css_select(self.article.doc, metaName)
99+
content = None
100+
101+
if meta is not None and len(meta) > 0:
102+
content = self.parser.getAttribute(meta[0], 'content')
103+
104+
if content:
105+
return content.strip()
106+
107+
return ''
108+
109+
def get_meta_description(self):
110+
"""\
111+
if the article has meta description set in the source, use that
112+
"""
113+
return self.get_meta_content("meta[name=description]")
114+
115+
def get_meta_keywords(self):
116+
"""\
117+
if the article has meta keywords set in the source, use that
118+
"""
119+
return self.get_meta_content("meta[name=keywords]")
120+
121+
def extract(self):
122+
return {
123+
"description": self.get_meta_description(),
124+
"keywords": self.get_meta_keywords(),
125+
"lang": self.get_meta_lang(),
126+
"favicon": self.get_favicon(),
127+
"canonical": self.get_canonical_link()
128+
}

0 commit comments

Comments
 (0)