【发布时间】:2019-08-20 02:47:16
【问题描述】:
我的问题几乎与:Scrapy - Why Item Inside For Loop Has The Same Value While Accessed in Another Parser
除了我有两个 For 循环,所以创建一个新项目会导致我丢失第一个抓取页面中的数据。
基本结构是:
知道第一个网址。
-
For 循环遍历已知 url
-
数据和下一个url的for循环
-
For 循环获取更多数据和下一个 url
更多数据和下一个网址。
更多数据和下一个网址。
产量
-
-
每页有 10-40 条数据,但我有一个简化的代码来查找 1-2。
import scrapy
class Product(scrapy.Item):
Date = scrapy.Field()
Name = scrapy.Field()
Winner_Name= scrapy.Field()
Match_Duration= scrapy.Field()
Loser_Url= scrapy.Field()
Winner_Birthday= scrapy.Field()
Loser_Birthday= scrapy.Field()
pass
import scrapy
from urllib.parse import urljoin
from items import Product
start = 2018
finish =2019
class QuotesSpider(scrapy.Spider):
name = "brief"
custom_settings = {'CONCURRENT_REQUESTS':1,'DOWNLOAD_DELAY':1}
def start_requests(self):
urls = "https://www.atptour.com/en/scores/results-archive?year=2018"
for year in range(start, finish):
next_page = urljoin(urls,"?year=" + str(year))
yield scrapy.Request(next_page, callback=self.parse, meta={'dont_obey_robotstxt': True},dont_filter=True)
def parse(self, response):
for tournament in response.css('tr.tourney-result'):
item = Product()
item['Date']=tournament.css('span.tourney-dates::text').get().replace("\r", '').replace("\n", '').replace("\t", '').strip(),
item['Name']= tournament.css('span.tourney-title::text').get().replace("\r", '').replace("\n", '').replace("\t", '').strip(),
Tourney_URL= response.urljoin(tournament.css('a.button-border::attr(href)').get())
yield scrapy.Request(Tourney_URL, callback=self.tourney_info, meta={'dont_obey_robotstxt': True, 'item':item},dont_filter=True)
def tourney_info(self, response):
table = response.css('table.day-table tbody')
rows = table.css('tr')
for row in rows:
item = response.meta['item']
names = row.css('td.day-table-name a::text').getall()
item['Winner_Name']= names[0].replace("\r", '').replace("\n", '').replace("\t", '').strip(),
Match_URL = response.urljoin(row.css('td.day-table-score a::attr(href)').get())
yield scrapy.Request(Match_URL, callback=self.matchinfo, meta={'dont_obey_robotstxt': True,'item':item},dont_filter=True)
def matchinfo(self, response):
item = response.meta['item']
table = response.css('table.match-stats-table')
mytime = response.css('td.time::text').get().replace("\r", '').replace("\n", '').replace("\t", '').strip()
factors = (60, 1, 1 / 60)
t1 = sum(i * j for i, j in zip(map(int, mytime.split(':')), factors))
item['Match_Duration'] = t1
item['Loser_Url']=response.urljoin(response.css('div.player-right-image a::attr(href)').get())
winner_url = response.urljoin(response.css('div.player-left-image a::attr(href)').get())
yield scrapy.Request(winner_url, callback=self.winnerinfo, meta={'dont_obey_robotstxt': True,'item':item},dont_filter=True)
def winnerinfo(self, response):
item = response.meta['item']
item['Winner_Birthday'] = response.css('span.table-birthday::text').get().replace("\r", '').replace("\n", '').replace("\t", '').strip()
yield scrapy.Request(item['Loser_Url'], callback=self.loserinfo, meta={'dont_obey_robotstxt': True, 'item': item},dont_filter=True)
def loserinfo(self, response):
item = response.meta['item']
item['Loser_Birthday'] = response.css('span.table-birthday::text').get().replace("\r", '').replace("\n", '').replace("\t", '').strip()
yield item
非常简化的结果是:
-
For 循环遍历已知 url(工作)
-
数据和下一个 url 的 For 循环(工作)
-
更多数据和下一个 url 的 For 循环(将为该循环中的所有数据提供相同的值)
更多数据和下一个网址。 (工作)
更多数据和下一个网址。 (工作)
产量
-
-
Scrapy 是否具有我所缺少的能够在整个抓取过程中保留一个项目的功能?
结果:
应该是:
A B C
A D E
A F G
B H I
B J K
是:
A B C
A B E
A B G
B H I
B H K
【问题讨论】:
-
您可以在
pipeline.py中过滤重复项:创建一个类变量saved_items = {}并在process_item()中检查它 -
我删除了关于重复项的句子,因为这不是主要问题。