Python 在Scrapy上的多个链接中爬行
我试图首先在这个网站的主页上搜索每年一张表格的链接。然后,我要刮每个网站,同时保持每年的记录 到目前为止,我的蜘蛛构造为:Python 在Scrapy上的多个链接中爬行,python,html,web-scraping,xpath,scrapy,Python,Html,Web Scraping,Xpath,Scrapy,我试图首先在这个网站的主页上搜索每年一张表格的链接。然后,我要刮每个网站,同时保持每年的记录 到目前为止,我的蜘蛛构造为: div = response.xpath('//*[@id="sidebar"]/div[1]/nav/ul/li[5]/div') hrefs = div.xpath('*//a').extract() splits = {} for href in hrefs: split = href.split('"')
div = response.xpath('//*[@id="sidebar"]/div[1]/nav/ul/li[5]/div')
hrefs = div.xpath('*//a').extract()
splits = {}
for href in hrefs:
split = href.split('"')
link = split[1]
date = split[2]
clean_date = "".join(re.findall("[^><a/]",date))
clean_link = "http://www.ylioppilastutkinto.fi" + str(link)
splits[clean_date] = clean_link
我的问题是我找不到一个有效的方法。在url上调用scrapy.Request
,只返回内容为
的响应。如果有一种方法,响应对象可以类似于Scrapy shell中的fetch
命令所给出的对象,那将是理想的,因为我已经基于使用该命令进行测试的选择逻辑
编辑:
这是目前为止所有的蜘蛛
其思想是运行第一个for循环以获取链接,然后运行第二个for循环以从所述链接提取表
import scrapy
import regex as re
from scrapy.http import HtmlResponse
import w3lib.html
class MainSpider(scrapy.Spider):
name = 'links'
allowed_domains = ['www.ylioppilastutkinto.fi/ylioppilastutkinto/pisterajat']
start_urls = ['https://www.ylioppilastutkinto.fi/ylioppilastutkinto/pisterajat/']
def parse(self, response):
div = response.xpath('//*[@id="sidebar"]/div[1]/nav/ul/li[5]/div')
hrefs = div.xpath('*//a').extract()
splits = {}
for href in hrefs:
split = href.split('"')
link = split[1]
date = split[2]
clean_date = "".join(re.findall("[^><a/]",date))
clean_link = "http://www.ylioppilastutkinto.fi" + str(link)
splits[clean_date] = clean_link
for date,url in splits.items():
resp = HtmlResponse(url)
table = resp.xpath('//*[@id="content"]/table/tbody')
rows = table.xpath('//tr')
data_dict = {"Category":[w3lib.html.remove_tags(num.get()) for num in rows[0].xpath('td')[1:]]}
for row in rows[1:]:
data = row.xpath('td')
title = w3lib.html.remove_tags(data[0].get())
nums = [w3lib.html.remove_tags(num.get()) for num in data[1:]]
data_dict[title] = nums
yield {
'Date': date,
'Scores': data_dict}
import scrapy
将正则表达式作为re导入
从scrapy.http导入HtmlResponse
导入w3lib.html
主卡盘类(刮擦卡盘):
名称='链接'
允许的_域=['www.ylioppilastutkinto.fi/ylioppilastutkinto/pisterajat']
起始URL=['https://www.ylioppilastutkinto.fi/ylioppilastutkinto/pisterajat/']
def解析(自我,响应):
div=response.xpath('/*[@id=“sidebar”]/div[1]/nav/ul/li[5]/div')
hrefs=div.xpath('*//a').extract()
拆分={}
对于hrefs中的href:
split=href.split(“”)
链接=拆分[1]
日期=拆分[2]
clean_date=“”.join(关于findall(“[^>初始化HtmlResponse(url)
不会完成任何事情,因为类本身不会发出请求
要向scrapy的调度程序添加请求,您需要生成一个请求,例如:yield scrapy.request(url,callback=self.parse)
也就是说,您可以对spider进行许多改进
- 使用scrapy的内置而不是字符串拆分
- 使用css选择器而不是硬编码的XPath
- 使用
selector.root.text
而不是w3lib.remove_标记
(完全删除依赖项)
以下是一个工作示例:
import scrapy
from scrapy.linkextractors import LinkExtractor
class MainSpider(scrapy.Spider):
name = 'links'
allowed_domains = ['www.ylioppilastutkinto.fi']
start_urls = ['https://www.ylioppilastutkinto.fi/ylioppilastutkinto/pisterajat/']
def parse(self, response):
le = LinkExtractor(
allow_domains=self.allowed_domains,
restrict_xpaths='//*[@id="sidebar"]/div[1]/nav/ul/li[5]/div',
)
for link in le.extract_links(response):
yield scrapy.Request(
url=link.url,
callback=self.parse_table,
cb_kwargs={ 'date': link.text },
)
def parse_table(self, response, date):
rows = response.css('#content table tbody tr')
if not rows:
print(f'No table found for url: {response.url}')
return
category = [char.root.text for char in rows[0].css('td strong')[1:]]
if not category:
category = [char.root.text for char in rows[0].css('td')[1:]]
for row in rows[1:]:
cols = row.css('td')
title = cols[0].root.text
nums = [col.root.text for col in cols[1:]]
yield {
'Date': date,
'Category': category,
title: nums
}
注意你的分类解析似乎不起作用。我不太确定你想提取什么,所以我将把这个留给你。不清楚你从哪个url开始?你能发布你的完整蜘蛛吗?fetch
做的是使用scrapy.Request
来请求url。你能显示蜘蛛吗到目前为止,你有r的代码吗?我添加了蜘蛛的其余部分。你需要产生请求。你完成了吗?好的,花了一点时间,测试并运行了建议的想法,是的,一切都很好。谢谢你的帮助。还让我对Scrapy做了更多的研究,以改进以前的蜘蛛。还有,是的,我没有重新开始ally还在做表格提取,因为我最担心的是先在那些网站上找到蜘蛛。
import scrapy
from scrapy.linkextractors import LinkExtractor
class MainSpider(scrapy.Spider):
name = 'links'
allowed_domains = ['www.ylioppilastutkinto.fi']
start_urls = ['https://www.ylioppilastutkinto.fi/ylioppilastutkinto/pisterajat/']
def parse(self, response):
le = LinkExtractor(
allow_domains=self.allowed_domains,
restrict_xpaths='//*[@id="sidebar"]/div[1]/nav/ul/li[5]/div',
)
for link in le.extract_links(response):
yield scrapy.Request(
url=link.url,
callback=self.parse_table,
cb_kwargs={ 'date': link.text },
)
def parse_table(self, response, date):
rows = response.css('#content table tbody tr')
if not rows:
print(f'No table found for url: {response.url}')
return
category = [char.root.text for char in rows[0].css('td strong')[1:]]
if not category:
category = [char.root.text for char in rows[0].css('td')[1:]]
for row in rows[1:]:
cols = row.css('td')
title = cols[0].root.text
nums = [col.root.text for col in cols[1:]]
yield {
'Date': date,
'Category': category,
title: nums
}