好的,我已经非常接近了,需要帮助才能越过终点线。我有两段文本想用 Scrapy 抓取。格式如下:
<html>
<div id="product-description">
<p>
Blah blah blah text text text reads: 874620. more text text.
<br>
<br>
<b>Brand:</b>
" Nintendo"
<br>
<b>Condition:</b>
" Good"
</p>
</div>
</html>
到目前为止,我只能获取粗体标题(品牌:、条件:),而不是我真正想要的文本(任天堂、好)。与正则表达式类似,我只抓取“reads:”而不是紧随其后的字符串,这就是我想要的 (874620)。这是我所在的位置:
response.xpath('//div[@id="product-description"]//p/b').extract_first()
response.xpath('//div[@id="product-description"]//p').re(r'reads.*')
请您参考如下方法:
您可以提取 <p> 的全文标记然后运行正则表达式从中提取相关信息
示例代码:
import re
from scrapy.selector import Selector
html = '''<html>
<div id="product-description">
<p>
Blah blah blah text text text reads: 874620. more text text.
<br>
<br>
<b>Brand:</b>
" Nintendo"
<br>
<b>Condition:</b>
" Good"
</p>
</div>
</html>'''
extracted_text = Selector(text=html).xpath('//div[@id="product-description"]//p//text()').extract()
text = u''.join(extracted_text)
regex = r'reads:\s*(?P<reads>\d+).*Brand:\s*" (?P<brand>\w+)".*Condition:\s*" (?P<condition>\w+)"'
results = re.search(regex, text, flags=re.DOTALL).groupdict()
results['reads'] = int(results['reads'])
print(results)
此代码输出:
{'reads': 874620, 'brand': u'Nintendo', 'condition': u'Good'}
更新:
让我们看看这段代码做了什么:
xpath
首先,extracted_text获取 <p> 中的所有文本使用 xpath 的标记 //div[@id="product-description"]//p//text() 这个 xpath 意味着:
- 给我所有的 id 属性匹配的 div “产品描述”
- 给我上面div里面的所有p标签
- 从这些 p 标签中获取文本
注意://而不是 /意味着在搜索标签时也包括 child 的 child 和他们的 child 等等。
运行此 xpath 返回 <p> 内标签的每个文本的字符串列表我们找到的标签。
在 xpath 之后,我们使用 u''.join(extracted_text) 将这个列表连接成大字符串.
获得我们想要的全文后,我们可以运行正则表达式从中提取相关数据。
正则表达式
让我们尝试分解正则表达式,看看它的含义:
reads:\s*(?P<reads>\d+).*Brand:\s*" (?P<brand>\w+)".*Condition:\s*" (?P<condition>\w+)"
reads:\s*(?P<reads>\d+) - 给我找一个以 reads: 开头的字符串.后跟零个或多个空格 \s*并创建一个名为 reads 的匹配组,其中包含 \d+表示一位或多位数字。
.*Brand:\s*" (?P<brand>\w+)" - 上面后面跟着零个或多个字符(任何字符),字符串Brand:又一次\s*零个或多个空格后跟双引号和单空格 " .在此之后创建另一个名为 brand 的组,其中包含 \w+表示一个或多个字母数字字母。
.*Condition:\s*" (?P<condition>\w+)" - 这个和上面第二部分一样,为condition
正则表达式使用标志 DOTALL 执行这意味着 . char 匹配所有字符(包括换行符),因为我们的匹配是跨多行的。
运行上述正则表达式后,我们提取 3 个匹配组并将读取匹配从字符串转换为 int。
我把这个例子上传到here其中包含详细信息及其交互性,因此您可以自己尝试。
