【问题标题】:scrapy/Python crawls but does not scrape datascrapy/Python 抓取但不抓取数据
【发布时间】:2017-09-04 14:44:39
【问题描述】:

作为一个scrapy的新手,我不明白为什么这个蜘蛛不会从一个网站爬取数据来爬取。我已经在 stackoverflow 中搜索了可能的答案,但我发现它没有得到充分解决。我正在尝试从网站上抓取一个小镇餐厅列表。我对要抓取的网站的安全特性没有详细的了解。问题是否与 XPath 选择元素有关?蜘蛛运行良好,只是它不抓取任何东西。您能否建议它为什么不刮以及如何解决问题。蜘蛛有以下代码:

try:
    from scrapy.spiders import Spider
    from urllib.parse import urljoin
    from scrapy.selector import Selector
    from scrapy.http import Request

except ImportError:
    print ("\nERROR IMPORTING THE NESSASARY LIBRARIES\n")

#scrapy.optional_features.remove('boto')


class YelpSpider(Spider):
    name = 'yelp_spider'
    allowed_domains=["yelp.com"]
    headers=['venuename','services','address','phone','location']

    def __init__(self):
        self.start_urls = ['https://www.yelp.com/springfield-il-us']

    def start_requests(self):
        requests = []
        for item in self.start_urls:
            requests.append(Request(url=item, headers={'Referer':'http://www.google.com/'}))
            return requests

    def parse(self, response):
        requests=[] 
        sel=Selector(response)
        restaurants=sel.xpath('//*[@id="wrap"]/div[4]/div/div[1]/div/div[3]/div[1]/div[1]/h1')
        items=[]
        for restaurant in restaurants:
            item=YelpRestaurantItem()
            item['venuename']=sel.xpath('//*[@id="wrap"]/div[4]/div/div[1]/div/div[3]/div[1]/div[1]/h1')
            item['services']=sel.xpath('//*[@id="wrap"]/div[4]/div/div[1]/div/div[3]/div[1]/div[2]/div[2]/span[2]/a[1]')
            item['address']=sel.xpath('//*[@id="wrap"]/div[4]/div/div[1]/div/div[4]/div[1]/div/div[2]/ul/li[1]/div/strong/address')
            item['phone']=sel.xpath('//*[@id="wrap"]/div[4]/div/div[1]/div/div[4]/div[1]/div/div[2]/ul/li[3]/span[3]')
            item['location']=sel.xpath('//*[@id="dropperText_Mast"]')
            item['url']=response.url
            items.append(item)
            yield item

我的 items.py 有以下代码:

import scrapy

class YelpRestaurantItem(scrapy.Item):
    # define the fields for your item here like:
    # name = scrapy.Field()
    url=scrapy.Field()
    venuename = scrapy.Field()
    services = scrapy.Field()
    address = scrapy.Field()
    phone = scrapy.Field()
    location=scrapy.Field()

【问题讨论】:

  • 我假设您遇到缩进问题,请更正问题中的代码。而且,您是否尝试过调试您的代码?也许在for restaurant ... 的每次迭代中打印一些东西?
  • 你想刮什么?蜘蛛搜索带有“wrap”的 id 属性的东西,但是当我打开开始 url 时,我没有找到任何匹配的东西。
  • @Casper ,我正在尝试抓取姓名、服务、地址、电话、位置。我还应该说,这是我第一次使用 xpath 和 scrapy。我刚刚为一家在 Chrome/Developer Tools 中突出显示的餐厅复制了 xpath。但是,我想在这个小镇上抓取一份餐馆企业列表,包括名称、服务、地址、电话和位置。

标签: python xpath web-scraping scrapy


【解决方案1】:

您的导入在这里没有那么好,但这可能是我这边的配置问题。我认为下面的刮板可以满足您的需求:

import scrapy

class YelpSpider(scrapy.Spider):
    name = 'yelp_spider'
    allowed_domains=["yelp.com"]
    headers=['venuename','services','address','phone','location']

    def __init__(self):
        self.start_urls = ['https://www.yelp.com/search?find_desc=&find_loc=Springfield%2C+IL&ns=1']

    def start_requests(self):
        requests = []
        for item in self.start_urls:
            requests.append(scrapy.Request(url=item, headers={'Referer':'http://www.google.com/'}))
            return requests

    def parse(self, response):
        for restaurant in response.xpath('//div[@class="biz-listing-large"]'):
            item={}
            item['venuename']=restaurant.xpath('.//h3[@class="search-result-title"]/span/a/span/text()').extract_first()
            item['services']=u",".join(line.strip() for line in restaurant.xpath('.//span[@class="category-str-list"]/a/text()').extract())
            item['address']=restaurant.xpath('.//address/text()').extract_first()
            item['phone']=restaurant.xpath('.//span[@class="biz-phone"]/text()').extract_first()
            item['location']=response.xpath('.//input[@id="dropperText_Mast"]/@value').extract_first()
            item['url']=response.url
            yield item

一些解释:

我更改了起始网址。这个网址实际上提供了所有餐馆的概览,而另一个没有(或者至少从我的位置查看时没有)。

我已经删除了管道,因为它没有在我的系统中定义,我无法使用代码中不存在的管道进行尝试。

解析函数是我对其进行真正更改的函数。您定义的 xpath 不是很清楚。现在代码循环遍历每个列出的餐厅。

response.xpath('//div[@class="biz-listing-large"]')

此代码捕获所有餐馆数据。我在 for 循环中使用了它,因此我们可以为每家餐厅执行操作。此数据在变量restaurant 中可用。

所以如果我想从餐厅提取数据,我会使用这个变量。另外,我们需要以. 开始xpath,否则脚本将从网页的开头开始(这与使用响应相同)。

为了理解我回答中的 xpath,我可以向您解释这一点,但有很多可用的文档,他们可能比我更能解释这一点。

Some documentation

And some more

请注意,我已将餐厅用于大多数 item 的值。 location 和 url 的值并不是真正的餐厅数据,而是位于网页的其他位置。这就是为什么这些值使用response 而不是restaurant

【讨论】:

  • 感谢您的热心回答,它有效,虽然它没有刮掉“电话”和“地址”,可能是语法错误?
  • 您是否对代码进行了任何更改?当我在这里运行爬虫时,它会返回项目的所有已定义属性。
  • 按照您的建议使用的代码,它填充了除“电话”和“地址”之外的其他字段。
  • 您可能想尝试使用-L DEBUG 运行脚本。当你这样做时,在日志中找到抓取的数据,看看地址和电话是否在那里。由于数据在这里正确返回,我猜它与 Scrapy 的其他一些设置有关。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2018-09-22
  • 2013-05-23
  • 2013-07-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-09-02
相关资源
最近更新 更多