如何使用scrapy抓取Ask引擎搜索结果?

How to scrape Ask engine search results using scrapy?

我创建了一个蜘蛛来从一组用户定义的关键字中抓取 Ask 搜索结果。但是,每当我 运行 命令 scrapy crawl pageSearch -o test.json 这会为我创建一个空的 test.json 文件时,我不知道为什么。为了创建这个 api,我受到了开发人员 page that showed how to scrape google SERPs and also the tutorial from the official scrapy documentation. Here is a git of what I get from the command line 的启发。我从堆栈溢出问题中搜索了解决方案,但没有成功。我从以下命令提示行相信:'scrapy.spidermiddlewares.httperror.HttpErrorMiddleware' 这是一个 http 错误,但在互联网上搜索后它不是,根据我的终端,我的机器人 运行 成功并且 url 地址我在代码中指定的 scraping 发生位置是有效的。就个人而言,我没有看到我的错误,所以我迷路了。这是我的代码:

import scrapy
import json
import datetime


class PagesearchSpider(scrapy.Spider):
    name = 'pageSearch'

    def start_requests(self):
        queries = [ 'love']
        for query in queries:
            url = 'https://www.ask.com/web?q='+query
            yield scrapy.Request(url, callback=self.parse, meta={'pos': 0})

    def parse(self, response):
           print(response.text)
           di = json.loads(response.text)
           pos = response.meta['pos']
           dt = datetime.now().strftime('%Y-%m-%d %H:%M:%S')
           for result in di['organic_results']:
               title = result['a.PartialSearchResults-item-title-link.result-link']
               snippet = result['p.PartialSearchResults-item-abstract']
               link = result['div.PartialSearchResults-item-url']
               item = {'title': title, 'snippet': snippet, 'link': link, 'position': pos, 'date': dt}
               pos += 1
               yield item

               next_page = di['pagination']['nextPageUrl']
               if next_page:
                   yield scrapy.Request(next_page, callback=self.parse, meta={'pos': pos})

                   #scrapy crawl pageSearch -o test.json

我用的是Windows10。另外,还请大家帮忙,谢谢!

我发现了两个问题:


第一个:

在你的输出中你可以看到

[scrapy.downloadermiddlewares.robotstxt] DEBUG: Forbidden by robots.txt: <GET https://www.ask.com/web?q=love>

这意味着它读取https://www.ask.com/robots.txt并且有规则

User-agent: *
Disallow: /web

scrapy 尊重它并跳过 url https://www.ask.com/web?q=love

您必须在 settings.py 中设置 ROBOTTXT_OBEY = False 才能将其关闭。

Scrapy 文档:ROBOTTXT_OBEY


第二个:

您使用 di = json.loads(response.text),这意味着您需要 JSON 数据,但此页面发送 HTML,您必须使用函数 response.css(...)response.xpath(...).get().attrib.get(...)、等等

Scrapy 文档:Selectors


工作代码:

您可以将所有代码放在一个文件 script.py 和 运行 中作为 python script.py 而无需创建项目。它还会自动将结果保存在 test.json 中,而无需使用 -o test.json

import scrapy
import datetime

class PagesearchSpider(scrapy.Spider):

    name = 'pageSearch'

    def start_requests(self):
        queries = [ 'love']
        for query in queries:
            url = 'https://www.ask.com/web?q='+query
            yield scrapy.Request(url, callback=self.parse, meta={'pos': 0})

    def parse(self, response):
        print('url:', response.url)
        
        start_pos = response.meta['pos']
        print('start pos:', start_pos)

        dt = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')    
        
        items = response.css('div.PartialSearchResults-item')
        
        for pos, result in enumerate(items, start_pos+1):
            yield {
                'title':    result.css('a.PartialSearchResults-item-title-link.result-link::text').get().strip(), 
                'snippet':  result.css('p.PartialSearchResults-item-abstract::text').get().strip(), 
                'link':     result.css('a.PartialSearchResults-item-title-link.result-link').attrib.get('href'), 
                'position': pos, 
                'date':     dt,
            }

        # --- after loop ---
        
        next_page = response.css('.PartialWebPagination-next a')
        
        if next_page:
            url = next_page.attrib.get('href')
            print('next_page:', url)  # relative URL
            # use `follow()` to add `https://www.ask.com/` to URL and create absolute URL
            yield response.follow(url, callback=self.parse, meta={'pos': pos+1})


# --- run without project, and save in file ---

from scrapy.crawler import CrawlerProcess

c = CrawlerProcess({
    #'USER_AGENT': 'Mozilla/5.0',
    # save in file CSV, JSON or XML
    'FEEDS': {'test.json': {'format': 'json'}},
    #'ROBOTSTXT_OBEY': True,  # this stop scraping
})
c.crawl(PagesearchSpider)
c.start()