Python Can';t多次刮取从不同搜索中得到的不同结果,而不是单个结果
我已经编写了一个脚本来解析从csv文件中获取的网页(Python Can';t多次刮取从不同搜索中得到的不同结果,而不是单个结果,python,python-3.x,web-scraping,scrapy,Python,Python 3.x,Web Scraping,Scrapy,我已经编写了一个脚本来解析从csv文件中获取的网页(名字和姓氏)中填写两个输入框时填充的链接名称。该csv文件包含数千个名称,我正试图使用这些名称来刮取链接的名称 问题是爬行器总是刮去姓氏的链接名称 如何刮取与每次搜索关联的个人链接名称? 这是几个按时间顺序排列的名字和姓氏供您参考[取自csv文件]: ANTONIO AMADOR ACOSTA JOHN ROBERT ADAIR ROBERT CURTIS ADAMEK CY RITCHIE
名字和姓氏)中填写两个输入框时填充的链接名称
。该csv文件包含数千个名称,我正试图使用这些名称来刮取链接的名称
问题是爬行器总是刮去姓氏的链接名称
如何刮取与每次搜索关联的个人链接名称
?
这是几个按时间顺序排列的名字和姓氏供您参考[取自csv文件]:
ANTONIO AMADOR ACOSTA
JOHN ROBERT ADAIR
ROBERT CURTIS ADAMEK
CY RITCHIE ADAMS
我试过这样做:
import csv
import scrapy
from scrapy.crawler import CrawlerProcess
class AmsrvsSpider(scrapy.Spider):
name = "amsrvsSpiderscript"
lead_url = "https://amsrvs.registry.faa.gov/airmeninquiry/Main.aspx"
def start_requests(self):
with open("document.csv","r") as f:
reader = csv.DictReader(f)
itemlist = [item for item in reader]
for item in itemlist:
yield scrapy.Request(self.lead_url,meta={"fname":item['FIRST NAME'],"lname":item['LAST NAME']},dont_filter=True, callback=self.parse)
def parse(self,response):
fname = response.meta.get("fname")
lname = response.meta.get("lname")
payload = {item.css('::attr(name)').get(default=''):item.css('::attr(value)').get(default='') for item in response.css("input[name]")}
payload['ctl00$content$ctl01$txtbxFirstName'] = fname
payload['ctl00$content$ctl01$txtbxLastName'] = lname
payload.pop('ctl00$content$ctl01$btnClear')
yield scrapy.FormRequest(self.lead_url,formdata=payload,dont_filter=True,callback=self.parse_content)
def parse_content(self,response):
name = response.css("a[id$='lnkbtnAirmenName']::text").get()
print(name)
if __name__ == "__main__":
c = CrawlerProcess({
'USER_AGENT': 'Mozilla/5.0',
'DOWNLOAD_TIMEOUT' : 5,
'LOG_LEVEL':'ERROR'
})
c.crawl(AmsrvsSpider)
c.start()
该站点中的结果如下所示:
电流输出:
CY RITCHIE ADAMS
CY RITCHIE ADAMS
CY RITCHIE ADAMS
CY RITCHIE ADAMS
预期产出:
ANTONIO AMADOR ACOSTA
JOHN ROBERT ADAIR
ROBERT CURTIS ADAMEK
CY RITCHIE ADAMS
您的url在一次请求后被过滤,这就是为什么它不会删除其他链接的原因。您可以添加自定义设置dont\u filter=True
,以避免重复URL
您可以参考以进一步了解首先,我认为您遇到的问题来自如何将DictReader
对象转换为列表
打印itemlist
将提供:
[OrderedDict([('ANTONIO AMADOR','JOHN ROBERT'),('ACOSTA','ADAIR')]),OrderedDict([('ANTONIO AMADOR','ROBERT CURTIS'),('ACOSTA','ADAMEK')]),OrderedDict([('ANTONIO AMADOR','CY RITCHIE'),('ACOSTA','ADAMS'))]
我认为这不是你想要的。为了解决这个问题,我使用了csv.reader(f)
,它将每一行读取为(fname,lname)
元组
我还做了一些其他更改,据我所知,没有必要一次又一次地请求表单页面,因此只需请求一次,然后为列表中的每个名称提交表单
最后,我还改变了空白的使用,只是为了提高我自己的可读性
导入csv
进口羊瘙痒
从scrapy.crawler导入crawler进程
AmsrvsSpider类(刮擦式卡盘):
name=“amsrvsSpiderscript”
导联url=”https://amsrvs.registry.faa.gov/airmeninquiry/Main.aspx"
起始URL=[”https://amsrvs.registry.faa.gov/airmeninquiry/Main.aspx"]
def解析(自我,响应):
以open(“document.csv”、“r”)作为f:
拆分名称=列表(csv.reader(f))
打印(拆分名称)
默认值_pload={item.css('::attr(name)').get(默认值=''):
css('::attr(value)').get(默认值=“”)
对于response.css中的项(“输入[名称]”)
}
默认\u pload.pop('ctl00$content$ctl01$btnClear'))
对于fname,拆分名称中的lname:
有效载荷=dict(默认载荷)
有效负载['ctl00$content$ctl01$txtbxFirstName']=fname
有效负载['ctl00$content$ctl01$txtbxLastName']=lname
打印(fname,lname)
生成scrapy.FormRequest(self.lead\u url,
formdata=有效载荷,
Don_filter=True,
callback=self.parse_内容
)
def解析_内容(自身、响应):
name=response.css(“a[id$='lnkbtnAirmenName']::text”).get()
印刷品(名称)
如果名称=“\uuuuu main\uuuuuuuu”:
c=爬网进程({
“用户代理”:“Mozilla/5.0”,
“下载超时”:5,
“日志级别”:“错误”
})
c、 爬行(AmsrvsSpider)
c、 开始()
这解决了您无法为每个名称生成请求的问题,并检索了所需的链接名称
请注意,我用于测试的document.csv如下所示:
ANTONIO AMADOR,ACOSTA
JOHN ROBERT,ADAIR
ROBERT CURTIS,ADAMEK
CY RITCHIE,ADAMS
我不确定到底出了什么问题,但您可以跳过parse()
输出:
ANTONIO AMADOR ACOSTA
ROBERT CURTIS ADAMEK
CY RITCHIE ADAMS
JOHN ROBERT ADAIR
这就是我成功的原因。事实证明,饼干在这里起着至关重要的作用。因此,有必要以正确的方式处理cookie以获得所需的输出。我还在settings.py
中使用了这个COOKIES\u ENABLED=True
工作脚本:
def get_fields():
with open("brian.csv","r") as f:
reader = csv.DictReader(f)
itemlist = [item for item in reader]
return itemlist
class AmsrvsSpider(scrapy.Spider):
name = "amsrvs"
lead_url = 'https://amsrvs.registry.faa.gov/airmeninquiry/Main.aspx'
start_urls = ['https://amsrvs.registry.faa.gov/airmeninquiry/Main.aspx']
def parse(self,response):
payload = {item.css('::attr(name)').get(default=''):item.css('::attr(value)').get(default='') for item in response.css("input[name]")}
payload.pop('ctl00$content$ctl01$btnClear')
for i,item in enumerate(get_fields()):
payload['ctl00$content$ctl01$txtbxFirstName'] = item['FIRST NAME']
payload['ctl00$content$ctl01$txtbxLastName'] = item['LAST NAME']
yield scrapy.FormRequest(self.lead_url,formdata=payload,meta={'cookiejar': i},dont_filter=True,callback=self.parse_result)
def parse_result(self,response):
item_content = response.css("[id$='lnkbtnAirmenName']::text").get()
print(item_content)
这可能是由于一个错误。你能调试代码吗?你能添加你的日志吗?是的,你就在那里。但是,即使在我使用该dont\u filter=True
时,也会出现另一个问题。脚本总是为不同的名字生成相同的信息,这意味着我使用了几个名字来获取他们的信息,但是脚本一次又一次地填充关于姓氏的信息。谢谢你的回答@Calimocho。它仍然多次产生相同的结果。这很奇怪,在我的机器上复制和粘贴上面的代码会产生您上面概述的预期输出。我会再次检查所有内容是否完全相同,如果您仍然有问题,每个名称可能需要它自己的初始请求和cookie jar。默认情况下,处理启用的cookie,因此设置cookies\u enabled=True
不会更改脚本的行为。但是,您的使用cookiejar
meta-key确实如此。在您的实现中,…meta={'cookiejar':i}
将创建i
独立的会话。
def get_fields():
with open("brian.csv","r") as f:
reader = csv.DictReader(f)
itemlist = [item for item in reader]
return itemlist
class AmsrvsSpider(scrapy.Spider):
name = "amsrvs"
lead_url = 'https://amsrvs.registry.faa.gov/airmeninquiry/Main.aspx'
start_urls = ['https://amsrvs.registry.faa.gov/airmeninquiry/Main.aspx']
def parse(self,response):
payload = {item.css('::attr(name)').get(default=''):item.css('::attr(value)').get(default='') for item in response.css("input[name]")}
payload.pop('ctl00$content$ctl01$btnClear')
for i,item in enumerate(get_fields()):
payload['ctl00$content$ctl01$txtbxFirstName'] = item['FIRST NAME']
payload['ctl00$content$ctl01$txtbxLastName'] = item['LAST NAME']
yield scrapy.FormRequest(self.lead_url,formdata=payload,meta={'cookiejar': i},dont_filter=True,callback=self.parse_result)
def parse_result(self,response):
item_content = response.css("[id$='lnkbtnAirmenName']::text").get()
print(item_content)