【问题标题】:Scrapy shell can't crawl information while xpath works in Chrome console当 xpath 在 Chrome 控制台中工作时,Scrapy shell 无法抓取信息
【发布时间】:2017-09-08 23:19:16
【问题描述】:

我正在开展一个收集大学教授联系信息的项目。 (所以它不是恶意的。) 教授页面是动态的。我通过 Chrome 网络找到了请求。但是,scrapy xpath 在浏览器上运行时不能在 scrapy shell 中运行。我什至尝试添加标题。 scrapy shell result

Chrome console result

import scrapy
from universities.items import UniversitiesItem


class UniversityOfHouston(scrapy.Spider):
    name = 'University_of_Houston'
    allowed_domains = ['uh.edu']
    start_urls = ['http://www.uh.edu/directory/']

    def __init__(self):
        self.lastName = ''

    def parse(self, response):
        self.lastName = 'An'
        query = "http://www.uh.edu/directory/proxy.php?q=" + self.lastName + \
                "&submit=Search&limit=250&loc=HR730&pos=faculty%7Cstaff&faculty=faculty&staff=staff&student=student"

        yield scrapy.Request(query, callback=self.parse_staff)

    def parse_staff(self, response):
        results = response.xpath('//dt/a/@href').extract()
        for result in results:
            query = 'http://www.uh.edu/directory/' + result
            yield scrapy.Request(query, callback=self.parse_item)

    def parse_item(self, response):

        item = UniversitiesItem()

        item['full_name'] = response.xpath('//h2[@class="single_title"]/text()').extract_first()
        item['university'] = 'University of Houston'
        item['discipline'] = response.xpath('//td/a[@class="org"]/text()').extract_first()
        item['title'] = response.xpath('//tr/td[@class="title"]/text()')
        item['email'] = response.xpath('//td/a[@title="email address"]/text()').extract_first()[7:]
        item['phone'] = response.xpath('//td[@class="tel"]/a/text()').extract_first()

        yield item

测试版:

import scrapy
from universities.items import UniversitiesItem


class UniversityOfHouston(scrapy.Spider):
    #name = 'University_of_Houston'
    name = 'uh2'
    allowed_domains = ['uh.edu']
    start_urls = ['http://www.uh.edu/directory/']

    def __init__(self):
        self.last_name = ''

    def parse(self, response):
        with open('kw.txt') as file_object:
            last_names = file_object.readlines()

        for ln in ['Lee', 'Zhao']:
            self.last_name = ln.strip()
            print('-----------------------------------------------------')
            print("scraping last name: ", self.last_name)
            query = "http://www.uh.edu/directory/proxy.php?q=" + self.last_name + \
                    "&submit=Search&limit=250&loc=HR730&pos=faculty%7Cstaff&faculty=faculty&staff=staff&student=student"

            yield scrapy.Request(query, callback=self.parse_staff)

    def parse_staff(self, response):
        results = response.xpath('//dt/a/@href').extract()
        for result in results:
            query_proxy = 'http://www.uh.edu/directory/' + result.replace("index.php", "proxy.php")
            yield scrapy.Request(query_proxy, callback=self.parse_item)

    def parse_item(self, response):
        full_name = response.xpath('//h2[@class="single_title"]/text()').extract_first()
        if full_name:
            if self.last_name in full_name.split():
                item = UniversitiesItem()
                item['fullname'] = full_name
                # last_name = full_name.split()[-1]
                # item['lastname'] = last_name
                # item['firstname'] = full_name[:-len(last_name)].strip()
                item['university'] = 'University of Houston'
                try:
                    item['department'] = response.xpath('//td/a[@class="org"]/text()').extract_first()
                    item['title'] = response.xpath('//tr/td[@class="title"]/text()').extract_first()
                    item['email'] = response.xpath('//td/a[@title="email address"]/text()').extract_first()
                    item['phone'] = response.xpath('//td[@class="tel"]/a/text()').extract_first()
                except ValueError:
                    pass

                yield item

【问题讨论】:

  • 打开 Firefox 转到 about:config 搜索 javascript.enabled 并将其设置为 false。然后在Firefox中打开您的页面。如果你没有看到你想要的数据,那么页面会使用 javascript 脚本,而 scrapy 不会这样做。你需要我们Scrapy+Splash组合或者你需要使用Scrapy+Selenium
  • 我没有firefox,但我会试试。我以前用过 Scrapy+Selenium。但它返回错误:selenium.common.exceptions.StaleElementReferenceException。我将延迟设置为20s它仍然不起作用。我正在考虑使用 Scrapy+Phantomjs。
  • 发布有问题的代码
  • @Tarun Lalwani 已发布。

标签: xpath scrapy web-crawler


【解决方案1】:

问题是因为数据是在网页上使用 AJAX 调用获取的。并且获取主页时数据不可用

将您的 parse_staff 函数更改为以下,它应该可以工作

def parse_staff(self, response):
    results = response.xpath('//dt/a/@href').extract()
    for result in results:
        query = 'http://www.uh.edu/directory/' + result
        query_proxy = "https://ssl.uh.edu/directory/" + result.replace("index.php", "proxy.php")
        yield response.follow(query_proxy, callback=self.parse_item)

【讨论】:

  • 哇,它有效。但是 query_proxy 不应该以 http://www.uh.edu/directory 开头吗?你在哪里找到https://ssl?
  • 在 chrome 开发者工具中,网络选项卡。在抓取之前,您应该始终检查页面在做什么
  • 是的,http://www.uh.edu/directory 这就是我在网络标签中看到的。
  • 页面然后调用这个URL,所以我们可以跳过这个页面直接去获取我们数据的那个页面
  • 这是另一个问题。我的脚本只能在结果中保存一项(我试图将其保存到 csv 文件中)。你能弄清楚为什么吗?我刚刚发布了一个测试版。
猜你喜欢
  • 2017-07-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-08-15
  • 2018-10-05
  • 2017-09-08
  • 1970-01-01
相关资源
最近更新 更多