scrapy爬虫抓取百度网页(结果列表页和原文页正文提取)

本项目能够针对给定的搜索关键词列表,抓取百度网页搜索的前N页搜索结果。

主要贡献点:通过综合利用正文提取工具(jparser+url2io),提高了搜索结果原文的正文提取成功率和准确率。

本文完整代码详见:https://github.com/Neo-Luo/scrapy_baidu

需求

提供搜索关键词列表,针对每个关键词,返回搜索结果页前N页的搜索结果,保存为csv文件。

保存字段:
(1)搜索结果列表页:标题,摘要,发布时间,原文链接。
(2)每一条搜索结果对应的正文。

爬虫设计

主要python包:requests+BeautifulSoup+jparser+url2io。
其中jparser、url2io都用于网页文本正文提取,url2io准确率高,但不稳定,解析错误时则调用jparser。通过两者结合使用来提高正文提取的效果。

jparser

url2io

主要代码

# -*- coding:utf-8 -*-
import os
import requests
import time
import csv
import re
from bs4 import BeautifulSoup
import urllib2
from jparser import PageModel
import url2io

token = 'xxxx' #请到url2io官网注册获取token
api = url2io.API(token)

headers = {
    'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
    'Accept-Language': 'en-us;q=0.5,en;q=0.3',
    'Cache-Control': 'max-age=0',
    'Connection': 'keep-alive',
    'User-Agent': 'Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:22.0) Gecko/20100101 Firefox/22.0'
}

SAVE_DIR = 'scrapy_data' #抓取数据存储路径
if not (os.path.isdir(SAVE_DIR)):
    os.makedirs(SAVE_DIR)

# 主函数    
def main():
    reader = csv.reader(open( 'query_text.csv', 'rb'))
    index = 0
    for line in reader:
        record_id = 1
        query_all = line[0]
        csvfile = open( SAVE_DIR +'/scrapy_result_%i.csv' % (index), 'wb')
        writer = csv.writer(csvfile)
        data = ['record_id','query','title','abstract','link','content']
        writer.writerows([data])
 
        query_array = re.split(u"[,;。!?]", query_all.decode('utf-8'))
        if(len(query_array)):
            for query in query_array:
                    PAGE_NUM = 2 #抓取页数设置
                
                for k in range(0, PAGE_NUM):
                    try:
                        #待抓取的网页地址
                        url = 'http://www.baidu.com/s?wd=%s&pn=%i' % (query,k*10)
                        content = requests.get(url,headers=headers)
                        #使用BeautifulSoup解析html
                        soup = BeautifulSoup(content.text,'html.parser')
                        title = []
                        abstract = []
                        link = []
                        content = []
                        allNews = soup.find_all('div', { 'class', 'result c-container '})
                        for hotNews in allNews:
                            h3 = hotNews.find(name = "h3", attrs = { "class": re.compile( "t")}).find('a')
                            title.append(h3.text.replace("\"",""))
                            div = hotNews.find(name = "div", attrs = { "class": re.compile( "c-abstract")})
                            abstract.append(div.text.replace("\"",""))
                            a = hotNews.find(name = "a", attrs = { "class": re.compile( "c-showurl")})
                            detail_url = a.get('href')
                            link.append(detail_url)
                            # 正文提取模块
                            try:
                            	# url2io初步尝试提取
                                ret = api.article(url=detail_url, fields=['text', 'next'])
                                content.append(ret['text'].replace('\r','').replace('\n',''))
                            except:
                                try:
                                	# 第一次提取失败,url2io第二次尝试提取
                                    time.sleep(1)
                                    ret = api.article(url=detail_url, fields=['text'])
                                    content.append(ret['text'].replace('\r','').replace('\n',''))
                                except:
                                    try:
                                    	# 第2次提取失败的话,改用jparser提取
                                        try:
                                            html = requests.get(detail_url,headers=headers).text.decode('utf-8')
                                        except:
                                            html = requests.get(detail_url,headers=headers).text.decode('gbk')
                                        pm = PageModel(html)
                                        result = pm.extract()
                                        ans = [ x['data'] for x in result['content'] if x['type'] == 'text']
                                        content.append(''.join(ans))
                                    except Exception as e:
                                        print(e)
                                        print(detail_url)
                                        content.append('')
                                        pass

                        #将数据写入csv
                        data = []                        
                        for i in range( 0, len(title)):
                            try:
                                data.append((record_id,query,title[i],abstract[i],link[i],content[i]))
                                record_id += 1
                            except Exception as err:
                                print(err)
                        writer.writerows(data)
                        print("Page: " + str(k+1) + " finished!")

                    except Exception as err:
                        print(err)
                        pass

            
        csvfile.close()


if __name__ == '__main__':
    main()


抓取结果展示

record_id,query,title,abstract,link,content
1,消息面看贸易战进入持久战当下只能说是短暂靴子落地美公布关税豁免程序,贸易战后操作思路_烽火通信(600498)聊吧_赢家聊吧【股吧】,“贸易战既然已经开始,时间上持久战的概率较大。而当下也只能说是短暂的靴子落地,随时还有再起烽火可能,美国公布了个关税豁免程序但那只是正常程序,切勿就…”,http://www.baidu.com/link?url=fJ5P3mDdJxPJPBMMaMXI66n0_l72H4Q-ouH3LrM6jwrPW3_Eknpa2LfH_fk3zh_29wqXlDRCR9--xoHr1YMLLa, 周五盘面情绪波动过激主要来源于中美贸易……短线宜做逆风的墙头草,即再跌不悲观,反弹则不能盲目乐观,操作上忌追涨杀跌。把控仓位、跟随市场热点小打小闹为好。
2,消息面看贸易战进入持久战当下只能说是短暂靴子落地美公布关税豁免程序,“保持淡定,为什么说“贸易战”并不可怕?”,“2018年3月26日 - 既然靴子还没有落地,就不必过于惊慌,意向在落实…周边市场的需求推动下,我认为长期看是利好消息…美商务部长:惩罚关税不会引发贸易战,最终会以谈判…”,http://www.baidu.com/link?url=SJ5MEHBKnkWGAdHs_6HCZgjvx1ou6ZVDxEA64Sp_Le5gLoXcyVzn7eL0GDzn4yMi7x5HxOmiMr0jdl_EOtEet_7TGJFxSYnbTIOjdJA81Y_, 霸越英百家号03-2619:31让我们先来回顾下当下热议的贸易战的由来——媒体错误描述贸易战经过3月8日,美国总统特朗普宣布,以损害国家安全为由……另外2017年出口对于GDP的贡献度只有18.5%,即使600亿美元产品征税导致出口额全部取消,对于中国GDP的影响也只有4%*18.5%=0.74%。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章