爬取内容为贵州省政府采购网中的省级标讯的标题、发布及更新时间、链接、具体内容。

scrapy框架

本次爬虫基于scrapy框架完成,官方文档为https://www.osgeo.cn/scrapy/intro/tutorial.html ,这里主要记录一些特殊处理。

URL构造

查看网站url可以发现,网站并不通过简单的url参数实现翻页,查看源代码,可发现如下js代码:

这里的翻页是通过js实现的,控制的参数为

location="/list-1153332561072666.html?pageNo="+n+"&pageSize="+s;

因此可构造start_urls为

start_urls = ["http://www.ccgp-guizhou.gov.cn/list-1153332561072666.html?pageNo={}".format(i) for i in range(1,15)]#15为当前页数,format()实现参数拼接遍历

数据获取

在初始页获取标题、发布时间、URL

检查元素,可发现所有标题在class = “xnrx”的同一代码块中,通过单纯的xpath表达式不能获取所有的标题(无下标时默认返回第一个元素),但xpath可通过下标访问符合的所有内容,因此可通过如下代码获取:

for data in response.xpath('//div[@class="xnrx"]/ul'):
       for i in range(0, 14):
           item = ScrapyspiderItem()
           item['title']= data.xpath('//div[@class="xnrx"]/ul/li/a/text()')[i].get()
           item['time']= data.xpath('//div[@class="xnrx"]/ul/li/span/text()')[i].get()
           url = data.xpath('//div[@class="xnrx"]/ul/li/a/@href')[i].get()
           matchobj =  re.match('/view', url)#正则表达式
               if matchobj is not None:
                  url = 'http://www.ccgp-guizhou.gov.cn' + url
           item['link']= url

针对URL,在阅读源码中可以发现爬取的链接仅为一部分,需要通过增加http://www.ccgp-guizhou.gov.cn头才能正常访问,但并不是所有的详情页链接都是以http://www.ccgp-guizhou.gov.cn开头的,比如有些链接直接指向微信公众号,则可通过简单的正则表达式实现拼接。

获取详细内容

使用requests库获取所有html代码并编码为utf-8:

html = requests.get(url).content  
soup = BeautifulSoup(html, 'html.parser', from_encoding='utf-8')

通过beautifulsoup获取info标签内的内容:

r = soup.select('#info')[0].get_text()

正则表达式去除多余的\n\s,获取新闻内容:

_content = re.sub(r'\n', "", r)
content = re.sub(r'\s', "", _content)
item['content']=content

正则表达式匹配获得发布时间:

updateTime = soup.select('div')[3].get_text()
updateTime = re.findall(r"发布时间:(\d{4}-\d{1,2}-\d{1,2})", updateTime)
item['update_time'] = updateTime

反爬机制

使用菜鸟教程的框架会遭遇反爬,即返回403,但使用官方文档中的scrapy shell则不会出现此问题,有待研究。

主要代码

# -*- coding: utf-8 -*-
import scrapy
import re
import requests
from bs4 import BeautifulSoup  

from scrapyspider.items import ScrapyspiderItem
class CcgpSpider(scrapy.Spider):
    name = 'ccgp'
    allowed_domains = ['ccgp-guizhou.gov.cn']
    start_urls = ["http://www.ccgp-guizhou.gov.cn/list-1153332561072666.html?pageNo={}".format(i) for i in range(1,15)]
    
    def parse(self, response):

        for data in response.xpath('//div[@class="xnrx"]/ul'):
            for i in range(0, 14):
               item = ScrapyspiderItem()
               item['title']= data.xpath('//div[@class="xnrx"]/ul/li/a/text()')[i].get()
               item['time']= data.xpath('//div[@class="xnrx"]/ul/li/span/text()')[i].get()
               
               url = data.xpath('//div[@class="xnrx"]/ul/li/a/@href')[i].get()
               matchobj =  re.match('/view', url)
               if matchobj is not None:
                  url = 'http://www.ccgp-guizhou.gov.cn' + url
               item['link']= url
               
               html = requests.get(url).content  
               soup = BeautifulSoup(html, 'html.parser', from_encoding='utf-8')
               
               r = soup.select('#info')[0].get_text()
               _content = re.sub(r'\n', "", r)
               content = re.sub(r'\s', "", _content)
               item['content']=content

               updateTime = soup.select('div')[3].get_text()
               updateTime = re.findall(r"发布时间:(\d{4}-\d{1,2}-\d{1,2})", updateTime)
               item['update_time'] = updateTime

               yield item

解决保存文件乱码

造成此问题主要是因为EXCEL采用ANSI编码,而csv文件采用utf-8编码,解决此问题可将文件用Notepad++打开,在编码中选择ANSI编码完成转换,之后再打开就是正常的excel文件了。


本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!

ARP欺骗攻击复现 下一篇