爬取内容为贵州省政府采购网中的省级标讯的标题、发布及更新时间、链接、具体内容。
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 协议 ,转载请注明出处!