前几天用selenium抓取了搜狗微信文章666篇,今天想用抓包工具fiddler进行抓包,同样实现抓取微信文章
还有就是,用一个递归调用无限抓取百度百科的词条简介,很简单的一个实现
知识储备:fiddler的基本使用(如何断点),一些常用python模块的使用,redis模块的使用,对深度遍历有一点点的理解。
首先是,抓取微信文章,很简单的实现。每一步的说明都在代码里,可以看的懂。
# coding : utf-8
from time import sleep
from threading import Thread
from bs4 import BeautifulSoup
import requests,pymongo
Client = pymongo.MongoClient()
da = Client.pythonSpider
db = da.weixinarticle_3v
# 在MongoDB里面建立一个数据集,用来存储数据
def request_func(url):
# 一个请求函数,用来确保请求的有效性
headers = {'User-Agent':'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/65.0.3325.162 Safari/537.36'}
html = requests.get(url,headers=headers)
html.encoding = 'utf-8'
# 将网页的编码,变为‘utf-8’
if html.status_code == 200:
return html.text
else:
return None
# 下面是两个构造url的函数,因为我们爬取的url有两种类型
# 一种是大标题下的一个页面
# 一种是加载更多时的url
def struct_big_url():
for big in range(0,21):
big_page = 'http://weixin.sogou.com/pcindex/pc/pc_{0}/pc_{0}.html'.format(big)
yield big_page
# 将函数做成一个url生成器
def struct_sub_url():
for big in range(0,21):
for sub in range(1,5):
sub_page = 'http://weixin.sogou.com/pcindex/pc/pc_{0}/{1}.html'.format(big,sub)
yield sub_page
# 解析页面的函数,提取一个页面的标题和文章的链接
def parser_pages(html):
Soup = BeautifulSoup(html,'lxml')
# 因为在两种url(上述)有两种页面结构,所以用错误捕捉的方式,考虑两种情况的解析
try:
news_list = Soup.find('ul',class_="news-list").find_all('li')
except Exception:
news_list = Soup.find('body').find_all('li')
for i in news_list:
try:
h3 = i.find('h3').find('a')
# 找到含有标题和文章链接的标签
article_url = h3.get('href')
article_title = h3.get_text().strip()
article_content = parser_one_page(article_url)
# parser_one_page函数用来提取一篇文章的内容,参数是这篇文章的url
db.insert_one({article_title:article_content})
# 插入数据库
except Exception:
pass
# 对一篇文章的解析,用于提取文章内容
def parser_one_page(url):
html = request_func(url)
Soup = BeautifulSoup(html,'lxml')
main_content = Soup.find('div',id='img-content')
h2 = main_content.find('h2').get_text()
all_ps = main_content.find_all('p')
entire_list = []
entire_list.append(h2)
for p in all_ps:
one_p = p.get_text()
entire_list.append(one_p)
entire_article = '\n'.join(entire_list)
# 连接文章内容
return entire_article
def get_big_page():
for i in struct_big_url():
html = request_func(i)
parser_pages(html)
sleep(1)
def get_sub_page():
for x in struct_sub_url():
html = request_func(x)
parser_pages(html)
sleep(1)
def main():
'''
用main函数开启了一个多进程
并有sleep方法控制爬取的速度
:return:
'''
threads = []
t1 = Thread(target=get_big_page,args=())
t2 = Thread(target=get_sub_page,args=())
threads.append(t1)
threads.append(t2)
for t in threads:
t.start()
for t in threads:
t.join()
if __name__ == '__main__':
main()
下面是无限抓取百度词条简介的代码,用心看也是可以看懂的啦!
# coding : utf-8
from bs4 import BeautifulSoup
import requests,redis
pool = redis.ConnectionPool(host='localhost',port=6379)
r = redis.Redis(connection_pool=pool)
# 请求函数
def request_func(url):
headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/65.0.3325.162 Safari/537.36'}
html = requests.get(url,headers=headers,verify=False)
if html.status_code == 200:
html.encoding = 'utf-8'
return html.text
return None
n = 0
def parser_page(url):
'''
这是一个递归函数,用于调用,这个函数是整个程序的核心
:param url:
:return:
'''
global n
n += 1
r.hsetnx('baiduurl',value=n,key=url)
'''
建立这个数据集用于检验和防止重复抓取同一个链接,从而陷入死循环
与下面的not r.hexists('baiduurl',url_new)联合使用,防止重复抓取
'''
html = request_func(url)
Soup = BeautifulSoup(html,'lxml')
main_content = Soup.find('div',class_='main-content')
title = main_content.find('h1').get_text()
content = main_content.find('div',class_="lemma-summary").get_text()
r.hsetnx('baiducontent',key=title,value=content)
all_as = main_content.find('div',class_="lemma-summary").find_all('a')
for a in all_as:
try:
url_new = 'https://baike.baidu.com' + a.get('href')
url_name = a.get_text()
if not r.hexists('baiduurl',url_new) and not r.hexists('baiducontent',url_name):
# 上面的语句就是防止陷入死循环的判断句
'''
只有新获得的链接没有存在于前面存放爬取过了的链接的数据集中
且新连接的关键词也米有存在于存放content的数据集中时
才会对此链接进行抓取
'''
parser_page(url_new)
# 这个循环利用的是深度遍历
except Exception:
pass
if __name__ == '__main__':
parser_page('https://baike.baidu.com/item/%E8%9A%8A%E5%AD%90/284876')
# 随便以一个词条的链接作为爬取的起始点