Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/html/70.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 在Scrapy上的多个链接中爬行_Python_Html_Web Scraping_Xpath_Scrapy - Fatal编程技术网

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
            }