【问题标题】:Scrapy returning None on querying by xpathScrapy 在通过 xpath 查询时返回 None
【发布时间】:2021-10-04 22:20:25
【问题描述】:

您好,我正在使用 srapy 抓取网站 https://www.centralbankofindia.co.in,我收到了回复,但通过 XPath 查找地址时,我没有收到任何回复

    start_urls = [
    "https://www.centralbankofindia.co.in/en/branch-locator?field_state_target_id=All&combine=&page={}".format(
        i
    )
    for i in range(0, 5)
]
brand_name = "Central Bank of India"
spider_type = "chain"
# //*[@id="block-cbi-content"]/div/div/div/div[3]/div/table/tbody/tr[1]/td[2]/div/span[2]
# //*[@id="block-cbi-content"]/div/div/div/div[3]/div/table/tbody/tr[2]/td[2]/div/span[2]
# //*[@id="block-cbi-content"]/div/div/div/div[3]/div/table/tbody/tr[3]/td[2]/div/span[2]
def parse(self, response, **kwargs):
    """Parse response."""
    # print(response.text)
    for id in range(1, 11):
        address = self.get_text(
            response,
            f'//*[@id="block-cbi-content"]/div/div/div/div[3]/div/table/tbody/tr[{id}]/td[2]/div/span[2]',
        )
        print(address)

    def get_text(self, response, path):
    sol = response.xpath(path).extract_first()
    return sol

网站中地址的span类没有唯一的id,是什么原因造成的?

【问题讨论】:

  • 这个页面似乎使用 JavaScript 添加元素,但scrapy 无法运行 JavaScript,您可能需要 Selenium 来控制可以运行 JavaScript 的真实网络浏览器。甚至还有模块scrapy-selenium
  • 或者你应该使用更少的标签但更多的类 - 和// 跳过一些标签。您还应该检查原始 HTML,因为 DevTools 中的某些浏览器可能会显示 tbody,但 HTML 可能没有。

标签: python web-scraping scrapy


【解决方案1】:

我认为你创建的xpath 太复杂了。您应该跳过一些元素并改用//

某些浏览器可能会在DevTools 中显示tbody,但它可能不存在于scrapy 从服务器获取的HTML 中,因此最好总是跳过它。

您可以使用extract() 代替tr[{id}]extract_first()

这个 xpath 对我有用。

all_items = response.xpath('//*[@id="block-cbi-content"]//td[2]//span[2]/text()').extract()
        
for address in all_items:
    print(address)

顺便说一句:我在xpath 中使用text() 来获取不带HTML 标记的地址。


完整的工作代码。

您可以将所有内容放在一个文件中并以python script.py 运行,而无需创建project

它将结果保存在output.csv

start_urls 中,我只设置了指向首页的链接,因为parse() 在 HTML 中搜索指向下一页的链接 - 所以它可以获得所有页面而不是 range(0, 5)

#!/usr/bin/env python3

import scrapy

class MySpider(scrapy.Spider):
    
    start_urls = [
        # f"https://www.centralbankofindia.co.in/en/branch-locator?field_state_target_id=All&combine=&page={i}"
        # for i in range(0, 5)
        
        # only first page - links to other pages it will find in HTML
        "https://www.centralbankofindia.co.in/en/branch-locator?field_state_target_id=All&combine=&page=0"
    ]
    
    name = "Central Bank of India"
    
    def parse(self, response):
        print(f'url: {response.url}')
        
        all_items = response.xpath('//*[@id="block-cbi-content"]//td[2]//span[2]/text()').extract()
        
        for address in all_items:
            print(address)
            yield {'address': address}

        # get link to next page
        
        next_page = response.xpath('//a[@rel="next"]/@href').extract_first()
        
        if next_page:
            print(f'Next Page: {next_page}')
            yield response.follow(next_page)
            
# --- run without project and save in `output.csv` ---

from scrapy.crawler import CrawlerProcess

c = CrawlerProcess({
    'USER_AGENT': 'Mozilla/5.0',
    # save in file CSV, JSON or XML
    'FEEDS': {'output.csv': {'format': 'csv'}},  # new in 2.1
})
c.crawl(MySpider)
c.start()

【讨论】:

    猜你喜欢
    • 2021-12-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-11-24
    • 2014-08-24
    • 2021-12-20
    • 2021-05-01
    • 2019-04-07
    相关资源
    最近更新 更多