Scrapy框架 + MongoDB数据库。
目标是获取人人车网上北京地区的所有二手车商品信息,包括汽车品牌,汽车种类,上牌年限,行驶里程数,二手车售价以及首付情况。
为了防止反爬,Scrapy框架中运用了随机请求头来获取信息。
开发环境
- python3.7
- Scrapy框架及其组件
- random模块
- pymongo模块
获取分析:
找到人人车网北京地区的二手车购车页面,目标是获取北京地区的所有品牌的二手车商品信息。
def parse(self, response):
brands = response.xpath("//*[@id='brand_more_content']/div/p//a")
for brand in brands:
brandname = brand.xpath("./text()").get()
brandurl = "https://www.renrenche.com"+brand.xpath("./@href").get()
yield scrapy.Request(url=brandurl,callback=self.parsepage)
通过查看源码发现,人人车网的二手车商品列表信息正好都在源码中呈现,这大大减少了难度(暂时)。
但以为可以肆无忌惮地获取信息的时候发现,果然没这么简单。源码中的元素信息与在网页上呈现出来的信息竟然不相同!再仔细观察,能发现二手车的标名,年份时间,排量以及里程数等都与我们看到的不相同!这就麻烦了,这无疑是人人车网的反爬了。
不慌,仔细观察,发现了什么不常见的东西。该元素的class属性好像与以往的不同,就开始猜测问题出在这里。
不出所料,是字体出现了问题。这里用了不常见的字体,也就是源码中的信息通过该字体呈现在了网页上。那下一步就破解该字体。
通过抓包发现,数字字体被打乱了顺序:
这就好办了,将正序的数字与该数字一一对应,或许就能得到破解。
def change(self,strs):
luan = [1,2,3,4,5,6,7,8,9,0]
luan = map(lambda a:str(a),luan)
zheng = [5,6,3,1,2,7,4,9,8,0]
zheng = map(lambda b:str(b),zheng)
okdict = dict(zip(luan,zheng))
okstr = []
for strone in strs:
if str(strone) in okdict.keys():
strone = okdict[strone]
okstr.append(strone)
else:
okstr.append(strone)
okstr = ''.join(okstr)
return okstr
事实证明,该字体反爬确实如此。
解决了网站的反爬策略,通过Scrapy框架完成了北京地区的所有二手车商品信息的获取。
结果展示:
(截至目前,北京地区11658辆二手车信息已完成入库。)