这是一个使用Python爬取公众号二维码的项目,爬取https://data.wxb.com(微信公众号推广平台) 下的所有公众号。同时记录一下整个过程中遇到的问题。
- http: urllib3
- db: pymysql
- parser: beautifulsoup,
单页面分析
- 请求 https://data.wxb.com/rank?category=1&page=1 (第一个类目下面的第一页,每页有20条数据)。
查看请求过程以及response发现,返回数据都是在
数据解析就非常简单了,使用正则匹配到对应的json就好了,显得非常完美了,但是意想不到的事情还在后面。
- 发送请求
- 设置header
“` python
user_agents = [
‘Opera/9.25 (Windows NT 5.1; U; en)’,
‘Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 1.1.4322; .NET CLR 2.0.50727)’,
‘Mozilla/5.0 (compatible; Konqueror/3.5; Linux) KHTML/3.5.5 (like Gecko) (Kubuntu)’,
‘Mozilla/5.0 (X11; U; linux i686; en-US; rv:1.8.0.12) Gecko/20070731 Ubuntu/dapper-security Firefox/1.5.0.12’,
‘Lynx/2.8.5rel.1 libwww-FM/2.14 SSL-MM/1.4.1 GNUTLS/1.2.9’
“Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; AcooBrowser; .NET CLR 1.1.4322; .NET CLR 2.0.50727)”,
“Mozilla/4.0 (compatible; MSIE 7.0; AOL 9.5; AOLBuild 4337.35; Windows NT 5.1; .NET CLR 1.1.4322; .NET CLR 2.0.50727)”,
‘Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/65.0.3298.4 Safari/537.36’
]
header = {
‘User-Agent’: user_agents[random.randint(0, 6)],
‘cookie’: ‘your cookie’
}
“`python
- 数据解析
- 从上面过程中,最终获取到了对应的json数据,json中包含了对应的category/source,以及每一个category下面的source的数量 totalCount
- 通过json数据,抽象出三个基本的方法,
- json 2 object
- 定义实体
- 对象转换
- 数据持久化
数据批量插入,在刚开始做批量的时候,数据库的完整性约束,导致一些数据插入失败,整个批量回滚。后来放宽数据库完整性约束,批量处理完毕后,在对数据进行二次清洗。
批量爬取
单个页面的爬取数据,分析数据,持久化完成之后。对于批量,直接for循环即可实现。但是现实并非如此完美,被爬取数据的网站做了限流控制,访问的时候出现 503 拒绝服务。
- 应对策略1
模拟浏览器,设置不同代理,如上代码中设置了7种不同的代理,随机使用其中一个,这样效果提升了不少。 - 应对策略2
header添加cookies,因为网站做了限制,当访问第二页的时候,需要让你登录,随便注册个账号,拿到对应的cookie,添加到header里面,完美。
当爬取差不多7-8页数据的时候,会出现一直报错(503),刷新页面发现,及时注册账号,添加cookie,网站也做了访问限制,需要输入验证码。
- 应对策略
这个比较low了,当出现503的时候,会直接将请求sleep住,人肉输入验证码,重复上次sleep的请求。大家有什么好的方法,可以讨论一下。
- 使用urllib3,完成http请求。
- bytes to str : bytes.decode(‘utf-8’)解码即可
- InsecureRequestWarning: Unverified HTTPS request is being made. https://urllib3.readthedocs.io/en/latest/advanced-usage.html#ssl-warnings。https需要添加证书。
4.被爬网站存在反爬限制,需要设置代理。
result = http.request(‘GET’, url, headers={‘User-Agent’: ‘User-Agent:Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 Safari/537.36’}) - 携带cookie模拟登陆
header ={
‘user-agent’:’agent’,
‘cookie’:’your cookie’
}
http = urllib3.PoolManager()
result = http.request(url,header=header) - insert category has error,params:{None},error:{unsupported operand type(s) for %: ‘function’ and ‘tuple’}
sql :insert_cate = “INSERT INTO category (cate_id, name) VALUES (%d, %s)”
exe:cursor.execute(insert_cate % (category.id, category.name))
更正为:
cursor.execute(insert_cate, (category.id, category.name)) - {%d format: a number is required, not str}
在数据表中id使用的类型是int, 传参的时候使用%d。导致上面报错,其实pymysql在执行的时候,会自动转换类型。所以%d可以改成%s。