python - 如果不使用scrapy中的请求,则无法解析自定义结果
问题描述
我创建了一个脚本,使用 scrapy 从 imdb.com 获取所有连接到不同演员姓名的链接,然后解析他们的前三个电影链接,最后刮取这些电影的名称director
和名称writer
。如果我坚持当前的尝试,我的脚本会完美无缺。但是,我在方法中使用了requests
模块(我不想这样做)parse_results
来获取自定义输出。
脚本的作用(考虑第一个命名链接,如Robert De Niro
):
这是我到目前为止写的(正在工作的):
import scrapy
import requests
from bs4 import BeautifulSoup
from scrapy.crawler import CrawlerProcess
class ImdbSpider(scrapy.Spider):
name = 'imdb'
start_urls = ['https://www.imdb.com/list/ls058011111/']
def parse(self, response):
soup = BeautifulSoup(response.text,"lxml")
for name_links in soup.select(".mode-detail")[:10]:
name = name_links.select_one("h3 > a").get_text(strip=True)
item_link = response.urljoin(name_links.select_one("h3 > a").get("href"))
yield scrapy.Request(item_link,meta={"name":name},callback=self.parse_items)
def parse_items(self,response):
name = response.meta.get("name")
soup = BeautifulSoup(response.text,"lxml")
item_links = [response.urljoin(item.get("href")) for item in soup.select(".filmo-category-section .filmo-row > b > a[href]")[:3]]
result_list = [i for url in item_links for i in self.parse_results(url)]
yield {"actor name":name,"associated name list":result_list}
def parse_results(self,link):
response = requests.get(link)
soup = BeautifulSoup(response.text,"lxml")
try:
director = soup.select_one("h4:contains('Director') ~ a").get_text(strip=True)
except Exception as e: director = ""
try:
writer = soup.select_one("h4:contains('Writer') ~ a").get_text(strip=True)
except Exception as e: writer = ""
return director,writer
c = CrawlerProcess({
'USER_AGENT': 'Mozilla/5.0',
})
c.crawl(ImdbSpider)
c.start()
输出上述脚本产生的(所需的):
{'actor name': 'Robert De Niro', 'associated name list': ['Jonathan Jakubowicz', 'Jonathan Jakubowicz', '', 'Anthony Thorne', 'Martin Scorsese', 'David Grann']}
{'actor name': 'Sidney Poitier', 'associated name list': ['Gregg Champion', 'Richard Leder', 'Gregg Champion', 'Sterling Anderson', 'Lloyd Kramer', 'Theodore Isaac Rubin']}
{'actor name': 'Daniel Day-Lewis', 'associated name list': ['Paul Thomas Anderson', 'Paul Thomas Anderson', 'Paul Thomas Anderson', 'Paul Thomas Anderson', 'Steven Spielberg', 'Tony Kushner']}
{'actor name': 'Humphrey Bogart', 'associated name list': ['', '', 'Mark Robson', 'Philip Yordan', 'William Wyler', 'Joseph Hayes']}
{'actor name': 'Gregory Peck', 'associated name list': ['', '', 'Arthur Penn', 'Tina Howe', 'Walter C. Miller', 'Peter Stone']}
{'actor name': 'Denzel Washington', 'associated name list': ['Joel Coen', 'Joel Coen', 'John Lee Hancock', 'John Lee Hancock', 'Antoine Fuqua', 'Richard Wenk']}
在上述方法中,我requests
在方法中使用模块parse_results
来获得所需的输出,因为我不能yield
在任何列表理解中使用。
如何让脚本在不使用的情况下产生准确的输出requests
?
解决方案
解决此问题的一种方法是使用Request.meta
跨请求保留项目的待处理 URL 列表,并从中弹出 URL。
正如@pguardiario 提到的那样,缺点是您一次仍然只处理该列表中的一个请求。但是,如果您有比配置的并发更多的项目,那应该不是问题。
这种方法看起来像这样:
def parse_items(self,response):
# …
if item_links:
meta = {
"actor name": name,
"associated name list": [],
"item_links": item_links,
}
yield Request(
item_links.pop(),
callback=self.parse_results,
meta=meta
)
else:
yield {"actor name": name}
def parse_results(self, response):
# …
response.meta["associated name list"].append((director, writer))
if response.meta["item_links"]:
yield Request(
response.meta["item_links"].pop(),
callback=self.parse_results,
meta=response.meta
)
else:
yield {
"actor name": response.meta["actor name"],
"associated name list": response.meta["associated name list"],
}
推荐阅读
- arrays - MIPS 汇编程序中的错误:“数据/堆栈中的错误地址”()
- javascript - 使用 for 方法而不是 if-else 方法设置微调器适配器
- python - 打开在 Python 中创建的文本文件会导致 TextEdit 挂起
- sql - 使用索引时嵌套循环连接发生两次
- java - 如何在静态上下文中引用非静态方法(在实例上调用它们以进行方法序列化)
- html - 中心导航栏文本
- xaml - Xamarin Forms 带有标签文本换行和边距的奇怪问题
- mysql - 当另一个表更新时表自动更新
- prolog - 如果交集为空,则返回 True,否则返回 False
- php - WordPress 如何使用 get_user_meta() 获取嵌套数组的数据