Scrapy - 在文本中使用“少于”标记的网站
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Scrapy - 在文本中使用“少于”标记的网站相关的知识,希望对你有一定的参考价值。
更新:
这是html的示例行,直接使用Chrome中的“copy outer html”进行复制。我在td和/ td之前添加了空格来显示实际的html,而不会在这篇文章中触发html:
<td class="elem">3Fb1<+1Lo<+3Sb1</td>
使用scrapy shell,我运行以下命令:
response.xpath('//table[@class="elm"][1]//td[@class="elem"]//text()')
响应的数据是:
3Fb1
但它应该是
3Fb1<+1Lo<+3Sb1
我相信选择器在第一个滴答符('<')处停止,因为它似乎是新html标记的开头(或者,我从技术上讲,它是td标记文本的结尾)。仔细观察,它确实显示编码使用<而不是'<'字符。我希望有一个简单的限定符,我可以添加到我的xpath请求中忽略这些,但是在一周后(在我几个小时内)谷歌搜索和阅读,我找不到任何东西。
任何帮助是极大的赞赏。
我是scrapy的新手,我一直致力于一个项目(个人,我的孩子)收集大量与花样滑冰得分相关的统计数据。得分统计广泛使用'<'和'<<'来表示得分细节(滑手称这些'滴答',我将用它来引用它们)。
分数在表格中报告,表格类“ele”和根据展示位置编号的表格,然后包含执行的滑冰元素和行数。
一个示例评分条目(表格中的单元格)可以是:2A<
其底层代码为:<td class="elem">2A<</td>
或者这个:2A+1Lo<+2F
其底层编码为:
<td class="elem">2A+1Lo<+2F</td>
我已经定义了对象(可能不是正确的术语)行来迭代,然后使用它来获取特定的单元格(第二个单元格始终是执行的元素):
elements['executed_element'] = row.xpath('td[2]//text()').extract()
当勾号出现在文本的末尾时(如第一个例子),我得到了所有东西,但是当它位于文本的中间(第二个例子)时,它会截断它之后的所有内容。
我会回去手工修复,但是我要提取几百万个数据点,所以这样做是不切实际的。
任何帮助这个新手将不胜感激。
抓取示例页面:http://www.usfigureskating.org/leaderboard/results/2018/25073/SEGM001.html
码:
def parse(self, response):
event = response.xpath('//title//text()').extract()
category_segment = response.xpath('//h2[@class="catseg"]//text()').extract()
skater_number = 1
for row in response.xpath('//table[@class="sum"]/tbody/tr[not(contains(@class,"thead"))]'):
skater_name = row.xpath('td[2]//text()').extract_first()
skater_place = row.xpath('td[1]//text()').extract_first()
skater_deductions = row.xpath('td[7]//text()').extract_first()
# capture elements detail
skater_table = skater_place
elements_id = 1
element_table = '//table[@class="elm"][' + str(skater_table) +']/tbody/tr[not(contains(@class,"thead"))]'
for row in response.xpath(element_table):
elements = {}
elements['Event'] = event
elements['Category_Segment'] = category_segment
elements['skater_name'] = skater_name
elements['elements_id'] = elements_id
elements['element_number'] = row.xpath('td[@class="num"]//text()').extract()
elements['executed_element'] = row.xpath('td[2]//text()').extract()
elements['element_info'] = row.xpath('td[3]//text()').extract()
elements['base_value'] = row.xpath('td[4]//text()').extract()
elements['bonus'] = row.xpath('td[5]//text()').extract()
elements['GOE'] = row.xpath('td[6]//text()').extract()
goe_table = str('.//td[@class="jud"]')
judge_pointer = 8
judge_number = 1
elements_id += 1
for cell in row.xpath(goe_table):
elements['Judge Number'] = judge_number
elements['Judge_GOE_Score'] = row.xpath('td[' + str(judge_pointer) + ']//text()').extract()
yield elements
judge_pointer += 1
judge_number += 1
我下载了你的页面,程序wget
and在文本编辑器中检查它 - 它没有使用<
用于<
所以scrapy有问题 - 但只有<<+
和<+
我用<<+
用<<+
和<+
取代了<+
body = response.body.replace(b'<<+', b'<<+').replace(b'<+', b'<+')
然后我创建选择器
selector = scrapy.Selector(text=body.decode('utf-8'))
我可以使用css()
,它给了我正确的结果
#!/usr/bin/env python3
import scrapy
class MySpider(scrapy.Spider):
name = 'myspider'
start_urls = ['http://www.usfigureskating.org/leaderboard/results/2018/25073/SEGM001.html']
def parse(self, response):
print('url:', response.url)
body = response.body.replace(b'<<+', b'<<+').replace(b'<+', b'<+')
selector = scrapy.Selector(text=body.decode('utf-8'))
i = 1
for x in selector.css('.elem::text').extract():
if 'Elements' in x:
print('---', i, '---')
i += 1
else:
print(x)
# --- it runs without project and saves in `output.csv` ---
from scrapy.crawler import CrawlerProcess
c = CrawlerProcess({
'USER_AGENT': 'Mozilla/5.0',
# save in CSV or JSON
#'FEED_FORMAT': 'csv', # 'json
#'FEED_URI': 'output.csv', # 'output.json
})
c.crawl(MySpider)
c.start()
结果:
Executed
--- 1 ---
2Ab1+2T
ChSt1
2Ab1
2Lz+1Lo+2Lo
2Lz
FSSp4
2F
CCoSp4
Executed
--- 2 ---
2Ab1
ChSt1
2Ab1+1Lo+2F
CCoSp2V
2Lz+2Lo
2Lo
2Lz
LSp4
Executed
--- 3 ---
CCoSp4
ChSt1
2Ab1+2Lo
2Lz+1Lo+2Lo
2Ab1
2Lz
2Fe
FSSp4
Executed
--- 4 ---
2Ab1+1Lo+2Lo
2Ab1
LSp4
ChSt1
2Lz
2F
2Lz+2T
CCoSp4
Executed
--- 5 ---
2Ab1
LSp2
ChSt1
2Ab1+1Lo+1Lo
2Lz+2Lo
2Lz
2F
CCoSp3
Executed
--- 6 ---
2Lz
1A
SSp3
ChSt1
2Lz+1Lo+2Lo
CCoSp3
2F+2Lo
2F
Executed
--- 7 ---
2F
2Ab1
CCoSp4
2Lz
2Ab1<+2T
ChSt1
2Lz+1Lo+2F
LSp4
Executed
--- 8 ---
1A
LSp4
ChSt1
2Lz
2Lz+2T
2Lo+2T+1Lo
2F
CCoSp4
Executed
--- 9 ---
2A<<
CCoSp4
ChSt1
2F+1Lo+2Lo
2Lze+2Lo
2Lze
2F
SSp4
Executed
--- 10 ---
2Lz
2Ab1
SSp3
ChSt1
2A<<+REP
2Lz+2Lo
2F
CCoSp4
Executed
--- 11 ---
FSSp4
2Ab1<+2Lo
ChSt1
2A<<
FCCoSp3
2F+2Lo<+1Lo<<
2Lz
2F
Executed
--- 12 ---
2A<<+1Lo+2Lo<
2Lze
SSp3
ChSt1
2A<<
2F
2F+2Lo<
CCoSp3
您遇到的问题是由于保留字符(小于符号<
)代替<
而导致HTML格式错误。
一个解决方法是在你的html5lib
上使用BeautifulSoup和response
解析器后端(如this answer中所示)。通过使用已解析的内容覆盖响应的正文,您应该能够使用当前的代码:
from bs4 import BeautifulSoup
from scrapy.http import TextResponse
# parse response body with BeautifulSoup
soup = BeautifulSoup(response.body, "html5lib")
# overwrite response body
response = TextResponse(url="my HTML string", body=str(soup))
# from here on use your code
event = response.xpath('//title//text()').extract()
...
希望这可以帮助!
这不是一个scrapy问题,而是一个lxml
问题。您仍然可以在这种情况下使用scrapy
,但使用不同的解析器:
>> from scrapy import Selector
>> sel = Selector(text=response.body, type="xml")
>> sel.xpath('//table[@class="elm"][1]//td[@class="elem"]//text()') # should return it correctly
您将不得不使用sel
从该页面而不是response
中提取信息。
已知问题已经是reported here
以上是关于Scrapy - 在文本中使用“少于”标记的网站的主要内容,如果未能解决你的问题,请参考以下文章