垃圾回调函数,如何解析几个页面?

2024-07-04 07:53:14 发布

您现在位置:Python中文网/ 问答频道 /正文

我想做一个爬虫,它从一个url(page1)开始,然后通过一个链接指向一个新的页面page2。在第2页,它应该跟在第3页的链接后面。然后我想在第3页上收集一些数据。在

但是,我不擅长抓取,不能让回调函数工作。我的代码是:

class allabolagnewspider(CrawlSpider):
name="allabolagnewspider"
# allowed_domains = ["byralistan.se"]
start_urls = [
    "http://www.allabolag.se/5565794400/befattningar"
]

rules = (
    Rule(LinkExtractor(allow = "http://www.allabolag.se",
                       restrict_xpaths=('//*[@id="printContent"]//a[1]'),
                       canonicalize=False),
         callback='parse_link1'),
)

def parse_link1(self, response):
    hxs = HtmlXPathSelector(response)
    return Request(hxs.xpath('//*[@id="printContent"]/div[2]/table/tbody/tr[4]/td/table/tbody/tr/td[2]/a').extract(), callback=self.parse_link2)

def parse_link2(self, response):
    for sel in response.xpath('//*[@id="printContent"]'):
        item = AllabolagnewItem()
        item['Byra'] = sel.xpath('/div[2]/table/tbody/tr[3]/td/h1').extract()
        item['Namn'] = sel.xpath('/div[2]/table/tbody/tr[3]/td/h1').extract()
        item['Gender'] = sel.xpath('/div[2]/table/tbody/tr[3]/td/h1').extract()
        item['Alder'] = sel.xpath('/div[2]/table/tbody/tr[3]/td/h1').extract()
        yield item

但是,当我运行它时,我收到以下错误消息: TypeError:请求url必须是str或unicode,获取列表:

如果我没有弄错,当我试图返回parse_link1的请求时,我会搞砸。我该怎么办?在

编辑:

以下是工作代码(虽然仍有一些问题,但具体问题已解决):

^{pr2}$

Tags: dividparseresponsetableextractitemh1
2条回答

parse_link1中,您将传递一个列表,它是SelectorList上的.extract()的结果(在hxs选择器上调用.xpath()的结果),作为url的值,Request构造函数的第一个参数,而预期只有一个值。在

使用.extract_first()代替:

return Request(hxs.xpath('//*[@id="printContent"]/div[2]/table/tbody/tr[4]/td/table/tbody/tr/td[2]/a').extract_first()

OP评论后编辑

^{pr2}$

这是由于XPath表达式“过于保守”,可能是您的浏览器Inspect工具给出的(我在Chrome中测试了XPath,它适用于this example page

问题在于.../table/tbody/tr/...。问题是<tbody>很少有人编写的真正的HTML页面,甚至是模板(由人编写)。 HTML希望一个<table>有一个<tbody>,但是没有人真正关心,浏览器处理得很好(并且他们注入丢失的<tbody>元素来承载<tr>行)

因此,尽管它不是严格等价的XPath,但通常可以:

  • 省略tbody/并使用table/tr模式
  • 或使用table//tr

使用scrapy shell查看它的实际操作:

$ scrapy shell http://www.allabolag.se/befattningshavare/de_Sauvage-Nolting%252C_Henri_Jacob_Jan/f6da68933af6383498691f19de7ebd4b
>>>
>>> # with XPath from browser tool (I assume), you get nothing for the "real" downloaded HTML 
>>> response.xpath('//*[@id="printContent"]/div[2]/table/tbody/tr[4]/td/table/tbody/tr/td[2]/a')
[]
>>>
>>> # or, omitting `tbody/`
>>> response.xpath('//*[@id="printContent"]/div[2]/table/tr[4]/td/table/tr/td[2]/a')
[<Selector xpath='//*[@id="printContent"]/div[2]/table/tr[4]/td/table/tr/td[2]/a' data=u'<a href="/befattningshavare/de_Sauvage-N'>]

>>> # replacing "/table/tbody/" with "/table//" (tbody is added by browser to have "correct DOM tree")
>>> response.xpath('//*[@id="printContent"]/div[2]/table//tr[4]/td/table//tr/td[2]/a')
[<Selector xpath='//*[@id="printContent"]/div[2]/table//tr[4]/td/table//tr/td[2]/a' data=u'<a href="/befattningshavare/de_Sauvage-N'>]
>>>
>>> # suggestion: use the <img> tag after the <a> as predicate
>>> response.xpath('//*[@id="printContent"]/div[2]/table//tr/td/table//tr/td/a[img/@alt="personprofil"]')
[<Selector xpath='//*[@id="printContent"]/div[2]/table//tr/td/table//tr/td/a[img/@alt="personprofil"]' data=u'<a href="/befattningshavare/de_Sauvage-N'>]
>>> 

此外,您还需要:

  • 获取“href”属性值(在XPath末尾添加@href
  • 建立一个绝对的网址。response.urljoin()是一个方便的快捷方式

继续在破壳中:

>>> response.xpath('//*[@id="printContent"]/div[2]/table/tr[4]/td/table/tr/td[2]/a/@href').extract_first()
u'/befattningshavare/de_Sauvage-Nolting%252C_Henri_Jacob_Jan_Personprofil/f6da68933af6383498691f19de7ebd4b'
>>> response.urljoin(u'/befattningshavare/de_Sauvage-Nolting%252C_Henri_Jacob_Jan_Personprofil/f6da68933af6383498691f19de7ebd4b')
u'http://www.allabolag.se/befattningshavare/de_Sauvage-Nolting%252C_Henri_Jacob_Jan_Personprofil/f6da68933af6383498691f19de7ebd4b'
>>> 

最后,您的回调可能会变成:

def parse_link1(self, response):
    # .extract() returns a list here, after .xpath()
    # so you can loop, even if you have 1 result
    #
    # XPaths can be multiline, it's easier to read for long expressions
    for href in response.xpath('''
        //*[@id="printContent"]
           /div[2]
            /table//tr[4]/td
             /table//tr/td[2]/a/@href''').extract():
        yield Request(response.urljoin(href),
                      callback=self.parse_link2)

hxs.xpath(...).extract()返回的是列表而不是字符串。 尝试迭代生成请求的列表,或者从列表中选择所需的正确url。在

之后,只有当页面中的链接是绝对路径时,它才会起作用。如果你需要建立绝对路径的话。在

相关问题 更多 >

    热门问题