如何使用Scrapy爬取微信公眾號的文章列表及連結

本文會結合Python的爬蟲框架Scrapy 和 微信搜尋引擎進行微信公眾號上的文章搜尋爬取,並將爬取到的文章標題以及文章的連結保存到Excel文件中,同時將結果文件通過email發送到自己的郵箱中。

工具/原料

Python3
Scrapy

創建微信公眾號爬蟲工程的基本框架

使用Scrapy命令創建爬蟲的基本框架代碼

scrapy startproject wechatFishman

使用Scrapy命令生存爬蟲的的主類文件

scrapy genspider wechatFishman mp.weixin.qq.com

安裝相關的python依賴包

安裝python Excel處理包

使用如下命令進行安裝:

sudo -H pip install openpyxl

分析搜狗微信搜尋的網頁結構

打開搜狗選擇微信搜尋選項進行搜尋

在搜尋欄輸入「智慧城管」關鍵詞進行搜尋,我們就可以看到在微信上的相關文章列表

搜尋網址爬取策略分析

1. 搜尋URL需要帶Type 參數:微信搜尋時type =2

2. 搜尋URL的關鍵詞query參數:網址中我們可以直接將搜尋關鍵詞作為query的參數

3. 在進行爬蟲時可以不需要其他參數

分析後我們在爬蟲中需要訪問的URL連接樣例如下:

http://weixin.sogou.com/weixin?type=2&query=智慧城管

搜尋結果爬取策略分析

1. 上一個步驟我們得到一個查詢結果的頁面

2. 查看查詢結果頁面的原始碼,可以發現文章列表都在

<ul class="news-list"> </ul>裡面

3.文章列表css定位:

<div class="txt-box">內的<a>元素中

所以我們可以通過  ul -> div ->a 的順序定位文章的列表以及連接

搜尋結果下一頁的爬取策略分析

1.下一頁的按鈕對應的原始碼如下:

<a id="sogou_next" href="?query=%E6%99%BA%E6%85%A7%E5%9F%8E%E7%AE%A1&_sug_type_=&sut=2307&lkt=1%2C1533556190561%2C1533556190561&s_from=input&_sug_=n&type=2&sst0=1533556190663&page=2&ie=utf8&w=01019900&dr=1" class="np" uigs="page_next">下一頁</a>

2. 我們可以共同 <a id="sogou_next">進行定位,找到下一頁的URL地址進行爬取

編寫爬蟲關鍵代碼

WechatfishSpider.py 主文件

# -*- coding: utf-8 -*-

import scrapy

from wechatFishman.items import WechatfishmanItem

from selenium import webdriver

from bs4 import BeautifulSoup as bs4

import time

import wechatFishman.settings as settings

class WechatfishSpider(scrapy.Spider):

name = 'wechatFish'

key_word=settings.SUBJECT_KEY_WORDS

allowed_domains = ['mp.weixin.qq.com','weixin.sogou.com','mmbiz.qpic.cn']

start_urls = ['http://weixin.sogou.com/weixin?type=2&query=%s&ie=utf8' %key_word]

def parse(self, response):

print("\n")

print("***********parse spider***************")

wechat_item = WechatfishmanItem()

driver = webdriver.PhantomJS()

driver.get(response.url)

#time sleep is very import to load the url

time.sleep(30)

soup = bs4(driver.page_source,'html.parser')

news_list=soup.find_all('ul', {'class':'news-list'})

for news_item in news_list:

txt_box_list = news_item.find_all('div', {'class':'txt-box'})

for txt_box in txt_box_list:

news_href=txt_box.find('a')

wechat_item["file_name"] = news_href.get_text().strip()

print("******************\n")

print("title :%s" % wechat_item["file_name"])

wechat_item["file_url"] = news_href.get("href")

print("href :%s" % wechat_item["file_name"])

yield wechat_item

#for prevision page

next_page=soup.find('a',{"id":'sogou_next'})

if next_page:

if len(next_page) == 0:

print("\n-------->Finished the spider")

return

next_page_link = next_page.get("href")

if next_page_link:

#the last element

next_page_link = "http://weixin.sogou.com/weixin"+ next_page_link

yield scrapy.Request(next_page_link, callback=self.parse)

else:

print("\n-------->No More Page")

driver.quit()

WechatfishmanItem.py:爬取結果項定義類

import scrapy

class WechatfishmanItem(scrapy.Item):

# define the fields for your item here like:

file_name = scrapy.Field()

file_url = scrapy.Field()

settings.py 打開中間件以及配置相關的常量值

FILE_SAVE_DIR='/home/hxb/wechat'

SUBJECT_FILE_NAME='深度學習'

SUBJECT_KEY_WORDS='深度學習'

ITEM_PIPELINES = {

'wechatFishman.pipelines.WechatfishmanPipeline': 1,

}

爬取結果處理類:WechatfishmanPipeline

# -*- coding: utf-8 -*-

import wechatFishman.settings as settings

from openpyxl import Workbook

from openpyxl import load_workbook

import os

import datetime

import smtplib

from email.mime.text import MIMEText

from email.mime.multipart import MIMEMultipart

from scrapy.xlib.pydispatch import dispatcher

from scrapy import signals

class WechatfishmanPipeline(object):

row_index = 0

file_path =  settings.FILE_SAVE_DIR+"/"+settings.SUBJECT_FILE_NAME+ "-"+datetime.date.today().strftime('%Y%m%d')+".xlsx"

def __init__(self):

dispatcher.connect(self.spider_closed,signals.spider_closed)

def process_item(self, item, spider):

print("***********WeChatFish Pipeline**************\n")

print("---------->save:%s" %item['file_name'])

dir_path="/home/hxb/wechat"

self.save_xls(item['file_name'],item['file_url'])

return item

def spider_closed(self,spider):

print("\n--------------->closed spider")

self.send_mail(self.file_path)

def save_xls(self,name,url):

print("\n******>Save to File %s" %self.file_path)

if not os.path.exists(self.file_path):

wb = Workbook()

ws = wb.active

ws.append(["Title","URL Link"])

self.row_index = self.row_index+1

wb.save(self.file_path)

load_wb = load_workbook(self.file_path)

ws = load_wb.active

self.row_index = self.row_index+1

ws.cell(self.row_index,1).value = name

ws.cell(self.row_index,1).hyperlink = url

ws.cell(self.row_index,2).value = url

ws.cell(self.row_index,2).hyperlink = url

load_wb.save(self.file_path)

def send_mail(self,file):

mail_host = 'smtp.163.com'

msg = MIMEMultipart('related')

msg['Subject'] = 'WeChat Spider result from'

msg['From'] = 'aaa@163.com'

#to_list = ['xxx@xxx.com','aaa@bbb.com','ccc@sss.com']

to_list= ['xxx@aaa.com']

msg['To']=','.join(to_list)

msg_doc = MIMEText(open(file,'rb').read(),'base64','utf8')

msg_doc.add_header('content-disposition','attachment',filename=settings.SUBJECT_FILE_NAME+datetime.date.today().strftime('%Y%m%d')+".xlsx")

msg.attach(msg_doc)

smtp = smtplib.SMTP(mail_host,25)

smtp.login('aaa@163.com','vicent$1981')

smtp.sendmail('aaa@163.com','aaa@ccc.com',msg.as_string())

smtp.quit()

運行爬蟲獲取內容

使用scrapy命令運行創建的爬蟲:

scrapy crawl wchatFish

查看爬蟲結果

在我們設定的目錄可以看到生成的爬蟲文件

在郵箱中我們也可以到爬蟲發送過來的excel結果文件

注意事項

爬取時需要間隔一定的時間,否則會觸發搜狗的發爬蟲措施導致無法爬取信息

本文內容整理自網絡, 文中所有觀點看法不代表淘大白的立場