【发布时间】:2019-09-18 07:45:39
【问题描述】:
我在scrapy 中编写了一个脚本,通过get_proxies() 方法使用新生成的代理发出代理请求。我使用requests 模块来获取代理,以便在脚本中重用它们。我要做的是从landing page 解析所有电影链接,然后从target page 获取每部电影的名称。我的以下脚本可以使用代理轮换。
我知道有一种更简单的方法来更改代理,就像这里描述的 HttpProxyMiddleware 但我仍然想坚持我在这里尝试的方式。
这是我目前的尝试(它一直使用新的代理来获取有效的响应,但每次都得到503 Service Unavailable):
import scrapy
import random
import requests
from itertools import cycle
from bs4 import BeautifulSoup
from scrapy.crawler import CrawlerProcess
def get_proxies():
response = requests.get("https://www.us-proxy.org/")
soup = BeautifulSoup(response.text,"lxml")
proxy = [':'.join([item.select_one("td").text,item.select_one("td:nth-of-type(2)").text]) for item in soup.select("table.table tbody tr") if "yes" in item.text]
return proxy
class ProxySpider(scrapy.Spider):
name = "proxiedscript"
handle_httpstatus_list = [503]
proxy_vault = get_proxies()
check_url = "https://yts.am/browse-movies"
def start_requests(self):
random.shuffle(self.proxy_vault)
proxy_url = next(cycle(self.proxy_vault))
request = scrapy.Request(self.check_url,callback=self.parse,dont_filter=True)
request.meta['https_proxy'] = f'http://{proxy_url}'
yield request
def parse(self,response):
print(response.meta)
if "DDoS protection by Cloudflare" in response.css(".attribution > a::text").get():
random.shuffle(self.proxy_vault)
proxy_url = next(cycle(self.proxy_vault))
request = scrapy.Request(self.check_url,callback=self.parse,dont_filter=True)
request.meta['https_proxy'] = f'http://{proxy_url}'
yield request
else:
for item in response.css(".browse-movie-wrap a.browse-movie-title::attr(href)").getall():
nlink = response.urljoin(item)
yield scrapy.Request(nlink,callback=self.parse_details)
def parse_details(self,response):
name = response.css("#movie-info h1::text").get()
yield {"Name":name}
if __name__ == "__main__":
c = CrawlerProcess({'USER_AGENT':'Mozilla/5.0'})
c.crawl(ProxySpider)
c.start()
为了确定请求是否被代理,我打印了response.meta 并且可以得到类似{'https_proxy': 'http://142.93.127.126:3128', 'download_timeout': 180.0, 'download_slot': 'yts.am', 'download_latency': 0.237013578414917, 'retry_times': 2, 'depth': 0} 的结果。
由于我过度使用链接来检查scrapy 中代理请求的工作方式,此时我收到503 Service Unavailable 错误,我可以在响应DDoS protection by Cloudflare 中看到这个关键字。但是,当我尝试使用 requests 模块应用我在此处实现的相同逻辑时,我得到了有效的响应。
My earlier question: why I can't get the valid response as (I suppose) I'm using proxies in the right way? [solved]
赏金问题:如何在我的脚本中定义
try/except子句,以便在与某个代理发生连接错误时尝试使用不同的代理?
【问题讨论】:
-
你能贴出你使用 requests 模块而不是 scrapy 时得到的 headers 吗?
-
当然。这是
requests.get(itemlink,proxies=proxy,headers={"User-Agent":"Mozilla/5.0"})@Edeki Okoh。 -
来自标头的实际响应而不是代码本身。查看代理以什么格式发送
标签: python python-3.x web-scraping scrapy