温馨提示:
爬虫玩得好,监狱进得早。数据玩得溜,牢饭吃个够。
《刑法》第 285 条,非法获取计算机信息系统数据罪。
违反国家规定,侵入前款规定以外的计算机信息系统或者采用其他技术手段,获取该计算机信息系统中存储、处理或者传输的数据,或者对该计算机信息系统实施非法控制,情节严重的,处三年以下有期徒刑或者拘役,并处或者单处罚金;情节特别严重的,处三年以上七年以下有期徒刑,并处罚金。
正文:
本篇文章我们将用requests爬取民政部的区划代码,并且实现增量爬虫
我们就不再分析这个网站了,因为这个和之前各个网站的分析差不了太多,就不过多分析了,但是我们在这里介绍这个网站和别的不一样的 反爬机制
第一个:
我们看这几个标签,F12响应出来的是这样的,我们在看网页源代码中是什么样子
我们看是没有tbody的,table标签完了之后,直接就是tr、td,因为我们是要用xpath提取数据的,标签准确是必须的,所以这就是这个网站的第一个反爬机制
第二个:
我们看这个最新的行政区划代码的链接,但是我们点进去在看链接是什么样的
这个链接就变了,这个是用到了一个URL地址跳转的技术,因为我们要用这个地址提取数据,所以我们要拿到准确的地址去响应数据才行
这就是这个网站的两个反爬机制,我们就都介绍完了,接下来就直接代码实现就好了
拿到最新月份的链接
//table/tr[1]/td[@class="arlisttd"]/a/@href
第二个反爬机制我们解决的代码,就是拿到真实链接:
<script>
window.location.href="http://preview.www.mca.gov.cn/article/sj/xzqh/2020/2020/202101041104.html";
</script>
这个就是真实的数据地址链接,那我们用正则把它提取出来就是:
regex = 'window.location.href="(.*?)"'
pattern = re.compile(regex, re.S)
其他的代码我们就不一一说了,跟之前的思路都一样
全部代码奉上:
import requests
from lxml import etree
from fake_useragent import UserAgent
import re
import redis
from hashlib import md5
import sys
class MzbSpider:
def __init__(self):
self.url = 'http://www.mca.gov.cn/article/sj/xzqh/2020/'
self.headers = {'User-Agent': UserAgent().random}
self.r = redis.Redis(host='localhost', port=6379, db=0)
def get_html(self, url):
"""请求URL功能函数"""
html = requests.get(url=url,
headers=self.headers).text
return html
def xpath_func(self, html, xpath_bds):
"""xpath提取功能函数"""
eobj = etree.HTML(html)
r_list = eobj.xpath(xpath_bds)
return r_list
def md5_url(self, url):
"""md5加密功能函数"""
s = md5()
s.update(url.encode())
return s.hexdigest()
def parse_html(self):
html = self.get_html(url=self.url)
# 提取最新月份的href
xpath_bds = '//table/tr[1]/td[@class="arlisttd"]/a/@href'
href_list = self.xpath_func(html, xpath_bds)
if href_list:
two_url = 'http://www.mca.gov.cn' + href_list[0]
finger = self.md5_url(two_url)
if self.r.sadd('mzb:spiders', finger) == 1:
# 提取详情页的具体数据
self.get_data(two_url)
else:
sys.exit('网站未更新')
else:
print('提取最新链接失败')
def get_data(self, two_url):
"""提取具体数据"""
# 1.在two_html中提取跳转之后的真实链接
false_html = self.get_html(url=two_url)
regex = 'window.location.href="(.*?)"'
pattern = re.compile(regex, re.S)
true_url_list = pattern.findall(false_html)
if true_url_list:
true_url = true_url_list[0]
true_html = self.get_html(url=true_url)
# 2.向真实链接发请求,拿到响应内容
two_xpath = '//tr[@height="19"]'
tr_list = self.xpath_func(true_html, two_xpath)
for tr in tr_list:
item = {}
item['name'] = tr.xpath('./td[3]/text()')[0]
item['code'] = tr.xpath('./td[2]/text() | ./td[2]/span/text()')[0]
print(item)
else:
print('真实链接提取失败')
def run(self):
self.parse_html()
if __name__ == '__main__':
spider = MzbSpider()
spider.run()