使用来自同一 URL 的多个 POST 数据进行抓取

Posted

技术标签:

【中文标题】使用来自同一 URL 的多个 POST 数据进行抓取【英文标题】:Scrape using multiple POST data from the same URL 【发布时间】:2013-07-14 23:36:09 【问题描述】:

我已经创建了一个蜘蛛,它收集公司名称和匹配的电话号码的列表。然后将其保存到 CSV 文件中。

然后我想使用 CSV 文件中的电话号码作为 POST 数据从另一个站点抓取数据。我希望它遍历相同的起始 URL,但只是抓取每个电话号码产生的数据,直到 CSV 文件中没有更多的号码。

这是我目前得到的:

from scrapy.spider import BaseSpider
from scrapy.http import Request
from scrapy.http import FormRequest
from scrapy.selector import htmlXPathSelector
from scrapy import log
import sys
from scrapy.shell import inspect_response
from btw.items import BtwItem
import csv

class BtwSpider(BaseSpider):
    name = "btw"
    allowed_domains = ["siteToScrape.com"]
    start_urls = ["http://www.siteToScrape.com/broadband/broadband_checker"] 

    def parse(self, response):
        phoneNumbers = ['01253873647','01253776535','01142726749']

        return [FormRequest.from_response(response,formdata='broadband_checker[phone]': phoneNumbers[1],callback=self.after_post)]


    def after_post(self, response):
       hxs = HtmlXPathSelector(response)
       sites = hxs.select('//div[@id="results"]')
       items = []
       for site in sites:
           item = BtwItem()

           fttcText = site.select("div[@class='content']/div[@id='btfttc']/ul/li/text()").extract()

           # Now we will change the text to be a boolean value
           if fttcText[0].count('not') > 0:
               fttcEnabled=0
           else:
               fttcEnabled=1

           item['fttcAvailable'] = fttcEnabled
           items.append(item)
       return items

目前我只是试图通过一个列表(电话号码)来循环,但到目前为止我什至还没有设法让它工作。一旦我知道该怎么做,我就可以自己从 CSV 文件中提取它。在当前状态下,它只是使用列表中索引为 1 的 phoneNumber。

【问题讨论】:

你能澄清一下这个问题吗?您可以使用for p in phoneNumbers: 在 Python 中循环遍历列表。但是,我怀疑这不是您要问的。 我能够运行上面的代码没有任何错误,那么什么不工作? 【参考方案1】:

假设您有一个phones.csv 文件,其中包含电话:

01253873647
01253776535
01142726749

这是你的蜘蛛:

import csv
from scrapy.item import Item, Field

from scrapy.spider import BaseSpider
from scrapy.http import Request
from scrapy.http import FormRequest
from scrapy.selector import HtmlXPathSelector


class BtwItem(Item):
    fttcAvailable = Field()
    phoneNumber = Field()


class BtwSpider(BaseSpider):
    name = "btw"
    allowed_domains = ["samknows.com"]

    def start_requests(self):
        yield Request("http://www.samknows.com/broadband/broadband_checker", self.parse_main_page)

    def parse_main_page(self, response):
        with open('phones.csv', 'r') as f:
            reader = csv.reader(f)
            for row in reader:
                phone_number = row[0]
                yield FormRequest.from_response(response,
                                                formdata='broadband_checker[phone]': phone_number,
                                                callback=self.after_post,
                                                meta='phone_number': phone_number)

    def after_post(self, response):
        hxs = HtmlXPathSelector(response)
        sites = hxs.select('//div[@id="results"]')

        phone_number = response.meta['phone_number']
        for site in sites:
            item = BtwItem()

            fttc = site.select("div[@class='content']/div[@id='btfttc']/ul/li/text()").extract()
            item['phoneNumber'] = phone_number
            item['fttcAvailable'] = 'not' in fttc[0]

            yield item

这是运行后抓取的内容:

'fttcAvailable': False, 'phoneNumber': '01253873647'
'fttcAvailable': False, 'phoneNumber': '01253776535'
'fttcAvailable': True, 'phoneNumber': '01142726749'

想法是使用start_requests 抓取主页,然后在回调中逐行读取csv 文件,并为每个电话号码(csv 行)读取yieldRequests。此外,通过meta 字典将phone_number 传递给回调,以便将其写入Item 字段(我认为您需要这个来区分项目/结果)。

希望对您有所帮助。

【讨论】:

以上是关于使用来自同一 URL 的多个 POST 数据进行抓取的主要内容,如果未能解决你的问题,请参考以下文章

mysql 来自同一列的多个连接具有不同的键

使用fiddler对手机APP进行抓包

同一个url对应多个视图函数,取第一个视图函数有效

在同一个脚本python中使用来自一个请求的第二个url请求的数据

爬虫数据抓包获取指定CSDN博主的全部文章信息

来自同一登录名的 Laravel Multi-auth(多个用户表)