平时在看公众号的时候,一直在想怎么才能抓取里面的文章。
知道网址就很容易抓取了,而每篇文章右上角都有一个用Safari打开的入口。把网址拷下来,抓取还不是易如反掌吗。
不过既然要用爬虫来抓取,那还是要批量显得更有效率一点。
那么现在,在搜狗和微信公众号的合作下,我们可以在PC端直接浏览公众号文章,及其列表!!
燃鹅,我这次的目标是平时挺喜欢看的DeepTech深科技。
为了更方便,我就直接锁定这个公众号的微信号。这是唯一的。
此时网址为 :
经观察可以看见,query这个参数的值就是我要搜索的mit-tr
接下来就是用网址的开发者工具得出获得这个公众号的入口网址
这个过程就省略。。。。。
直接上代码
def getWeixinhao(sgUrl):
head = {'User-Agent' : r'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/53.0.2785.104 Safari/537.36 Core/1.53.3103.400'}
request1 = request.Request(sgUrl, headers = head)
response = request.urlopen(request1)
sgSoup = BeautifulSoup(response, 'lxml')
eachLi = sgSoup.find_all('li')
for li in eachLi:
if(li.find(class_ = 'tit') != None):
getData(li.find(class_ = 'tit').a.get('href'))
if __name__ == '__main__':
sys.stdout = io.TextIOWrapper(sys.stdout.buffer,encoding='utf-8')
# 设置递归深度
sys.setrecursionlimit(1000000)
weixinHao = 'mit-tr'
'''
因为网址这里,如果有多个%,后面那个%(weixinHao)就会不知道
匹配哪个, 所以是%的就用%%来表示。
'''
getWeixinhao('http://weixin.sogou.com/weixin?type=1&s_from=input&query=%s&ie=utf8&_sug_=y&_sug_type_=&w=01019900&sut=3706&sst0=1505180448968&lkt=5%%2C1505180447462%%2C1505180448866' %(weixinHao))
记得把自己伪装成不是爬虫啊, 现在很多网站都不喜欢机器人浏览它的页面呢。
然后接下来我们就要获取其文章列表了,其实套路都一摸一样吧。
不过我想试试 selenium + PhantomJS 的效果,这个组合的用处主要用于抓取动态页面—js。
def getData(url):
headUrl = 'https://mp.weixin.qq.com'
browser = webdriver.PhantomJS()
browser.get(url)
soup = BeautifulSoup(browser.page_source, 'lxml')
urlSet = soup.find_all('h4')
# 获取每篇文章 url
for url in urlSet:
getContent('%s%s' %(headUrl, url.get('hrefs')))
# 设置时间间隔,减轻服务器负担并让别人认为你更像个人类
time.sleep(5)
browser.quit()
获取内容后我就可以获得它的内容了, 因为图片的下载速度和文章的下载速度差得有点远,所以我选择采用两个进程来分别处理图片和文章并存放到不同的文件夹中。
爬取内容中,最耗时间的其实就是如何获得想要内容的TAG并得到它的内容。
def getContent(url):
head = {'User-Agent' : r'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/53.0.2785.104 Safari/537.36 Core/1.53.3103.400'}
request1 = request.Request(url, headers = head)
response = request.urlopen(request1)
soup = BeautifulSoup(response, 'lxml')
title = soup.find(class_ = 'rich_media_title')
content = soup.find(class_ = 'rich_media_content ')
pA = Process(target = getImage, args = (content, title,))
pI = Process(target = getArticle, args = (content, title))
pA.start()
pI.start()
pA.join()
pI.join()
print('抓取完成 : %s' %(str(datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S'))))
def getArticle(content, title):
print('开始抓取文本 : %s' %(str(datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S'))))
eachP = content.find_all('p')
with open(file = 'ArticleFloder/%s.txt' %(title.get_text().split()[0]), mode = 'a', encoding = 'utf-8') as article:
for p in eachP:
text = p.find_all('span')
if len(text) > 0:
for s in text:
if 'ArticleFloder' not in os.listdir():
os.makedirs('ArticleFloder')
article.write(s.get_text())
article.write('\n')
print('完成文本下载 : %s' %(str(datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S'))))
def getImage(content, title):
print('开始抓取图片 : %s' %(str(datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S'))))
i = 0
imgSet = content.find_all('img')
if 'imgFloder' not in os.listdir():
os.makedirs('imgFloder')
for img in imgSet:
if 'gif' not in img.get('data-src'):
urlretrieve(url = img.get('data-src') , filename = 'imgFloder/%s%s.jpg' %(title.get_text().split()[0], i))
else:
urlretrieve(url = img.get('data-src') , filename = 'imgFloder/%s%s.gif' %(title.get_text().split()[0], i))
i+= 1
print('完成图片下载 : %s' %(str(datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S'))))
在控制台中就是这个效果。
文件夹
不过我代码里面并没有区分内容的附图和广告的附图,所以可以看到很多重复的图片,同时也影响了下载的速度。这是不足之处之一。
最后还是附上一个全代码吧:
# -*- coding:utf-8 -*-
import urllib.request as request
from urllib.request import urlretrieve
from bs4 import BeautifulSoup
from multiprocessing import Process
from selenium import webdriver
import time, datetime
import sys, io, os
def getData(url):
headUrl = 'https://mp.weixin.qq.com'
browser = webdriver.PhantomJS()
browser.get(url)
# result = reponse.find_element_by_class_name('weui_media_title')
soup = BeautifulSoup(browser.page_source, 'lxml')
urlSet = soup.find_all('h4')
for url in urlSet:
getContent('%s%s' %(headUrl, url.get('hrefs')))
time.sleep(5)
# break
browser.quit()
def getContent(url):
head = {'User-Agent' : r'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/53.0.2785.104 Safari/537.36 Core/1.53.3103.400'}
request1 = request.Request(url, headers = head)
response = request.urlopen(request1)
soup = BeautifulSoup(response, 'lxml')
title = soup.find(class_ = 'rich_media_title')
content = soup.find(class_ = 'rich_media_content ')
pA = Process(target = getImage, args = (content, title,))
pI = Process(target = getArticle, args = (content, title))
pA.start()
pI.start()
pA.join()
pI.join()
print('抓取完成 : %s' %(str(datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S'))))
def getArticle(content, title):
print('开始抓取文本 : %s' %(str(datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S'))))
eachP = content.find_all('p')
with open(file = 'ArticleFloder/%s.txt' %(title.get_text().split()[0]), mode = 'a', encoding = 'utf-8') as article:
for p in eachP:
text = p.find_all('span')
if len(text) > 0:
for s in text:
if 'ArticleFloder' not in os.listdir():
os.makedirs('ArticleFloder')
article.write(s.get_text())
article.write('\n')
print('完成文本下载 : %s' %(str(datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S'))))
def getImage(content, title):
print('开始抓取图片 : %s' %(str(datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S'))))
i = 0
imgSet = content.find_all('img')
if 'imgFloder' not in os.listdir():
os.makedirs('imgFloder')
for img in imgSet:
if 'gif' not in img.get('data-src'):
urlretrieve(url = img.get('data-src') , filename = 'imgFloder/%s%s.jpg' %(title.get_text().split()[0], i))
else:
urlretrieve(url = img.get('data-src') , filename = 'imgFloder/%s%s.gif' %(title.get_text().split()[0], i))
i+= 1
print('完成图片下载 : %s' %(str(datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S'))))
def getWeixinhao(sgUrl):
head = {'User-Agent' : r'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/53.0.2785.104 Safari/537.36 Core/1.53.3103.400'}
request1 = request.Request(sgUrl, headers = head)
response = request.urlopen(request1)
sgSoup = BeautifulSoup(response, 'lxml')
eachLi = sgSoup.find_all('li')
for li in eachLi:
if(li.find(class_ = 'tit') != None):
getData(li.find(class_ = 'tit').a.get('href'))
if __name__ == '__main__':
sys.stdout = io.TextIOWrapper(sys.stdout.buffer,encoding='utf-8')
sys.setrecursionlimit(1000000)
weixinHao = 'mit-tr'
getWeixinhao('http://weixin.sogou.com/weixin?type=1&s_from=input&query=%s&ie=utf8&_sug_=y&_sug_type_=&w=01019900&sut=3706&sst0=1505180448968&lkt=5%%2C1505180447462%%2C1505180448866' %(weixinHao))