Dust8 的博客

读书百遍其义自见

0%

爬虫与docker

最近又写了个爬虫, 爬美团的商家.总结一下新写法.
因为接口是加密的,懒得去找参数了,直接用浏览器渲染, 试了下 request-html 效果不好, 也不想用 pyppeteer 来写, 选择了无脑的渲染服务 splash.

javascript 渲染服务

splash 安装 直接用 docker 来安装, 方便快捷

1
docker run -it -p 8050:8050 --rm scrapinghub/splash

因为渲染页面会执行服务端的识别代码, 所以需要不断的重开容器来避免请求数太多

1
sudo docker stop $(sudo docker ps -f ancestor=scrapinghub/splash -q) && sudo docker run -it -d -p 8050:8050 --rm scrapinghub/splash

可以把它放到定时任务里面,例如半个小时重开一次

1
2
# crontab -e
30 * * * * sudo docker stop $(sudo docker ps -f ancestor=scrapinghub/splash -q) && sudo docker run -it -d -p 8050:8050 --rm scrapinghub/splash

代理服务

由于有反爬, 所以需要不停的换 ip 地址, 不然会出现验证码等反爬响应.买的话性价比也不高, 选择了开源的自建代理池 https://github.com/kagxin/proxy-pool 也是支持用 docker 部署

重试库

免费代理质量一般都不咋样, 所以需要不停的重试来保障请求的完整.下面是很粗暴的解析不到数据就主动引发错误来重试.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
from retrying import retry

splash_url = "http://localhost:8050/render.html"

@retry
def get_shop_urls(url, headers=None):
proxy = get_proxy()
loggers.info(f"get_shop_urls proxy {proxy} {url}")
params = {
"url": url,
"http_method": "GET",
"headers": {
"Accept-Language": "zh-CN,zh;q=0.9,en;q=0.8",
"user-agent": random.choice(USER_AGENTS),
},
"wait": 2,
"images": 0,
"proxy": proxy,
}
html = requests.post(
splash_url,
data=json.dumps(params),
headers={"Content-Type": "application/json"},
).text

if "对不起" in html:
return []

tree = fromstring(html)
links = []
for item in tree.xpath('//ul[@class="list-ul"]//div[@class="info"]//a/@href'):
links.append(item)

if not links:
raise ValueError()

return links

参考链接