这两天一直整一个大作业具体内容是从网站上爬取信件内容进行操作。这两天一直在整这个内容,到现在是爬了出来。
这是信件的网址老师给的网址已更新,这是我从同学哪里要的网址,有了网址,第一步是看要爬取的内容以及怎么获取网站上的相关信息。
这是网站的页面,我在点击下一页时发现并没用跳转页面,所以觉得事情没有那么简单,通过查看后台的传输发现其实通过ajax传输信息的。
网站获取的信息通过Ajax请求之后从http://www.beijing.gov.cn/hudong/hdjl/com.web.search.mailList.mailList.biz.ext获得信息。
ajax传输信息参数
我有学习了简单的scrapy爬虫框架,首先通过命令行创建一个新的scrapy项目。相关命令
scrapy startproject 项目名 #创建项目
scrapy genspider 爬虫名 网址 #生成spider文件(生成模板)
相关代码
import json
import random
import string
import scrapy
class XinjianSpider(scrapy.Spider):
name = 'xinjian'
allowed_domains = ['www.beijing.gov.cn']
# custome_setting可用于自定义每个spider的设置,而setting.py中的都是全局属性的,当你的
# scrapy工程里有多个spider的时候这个custom_setting就显得很有用了
custom_settings = {
"DEFAULT_REQUEST_HEADERS": {
'authority': 'www.beijing.gov.cn',
# 请求报文可通过一个“Accept”报文头属性告诉服务端 客户端接受什么类型的响应。
'accept': 'application/json, text/javascript, */*; q=0.01',
# 指定客户端可接受的内容编码
'accept-encoding': 'gzip, deflate',
# 指定客户端可接受的语言类型
'accept-language': 'zh-CN,zh;q=0.9',
'Connection': 'keep-alive',
# 就是告诉服务器我参数内容的类型,该项会影响传递是from data还是payload传递
'Content-Type': 'text/json',
# 跨域的时候get,post都会显示origin,同域的时候get不显示origin,post显示origin,说明请求从哪发起,仅仅包括协议和域名
'origin': 'http://www.beijing.gov.cn',
# 表示这个请求是从哪个URL过来的,原始资源的URI
'referer': 'http://www.beijing.gov.cn/hudong/hdjl/com.web.search.mailList.flow',
# 设置请求头信息User-Agent来模拟浏览器
'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.130 Safari/537.36',
'x-requested-with': 'XMLHttpRequest',
# cookie也是报文属性,传输过去
'cookie': 'HDJLJSID=39DBD6D5E12B9F0F8834E297FAFC973B; __jsluid_h=e6e550159f01ae9aceff30d191b09911; sensorsdata2015jssdkcross=%7B%22distinct_id%22%3A%2216f9edc47471cb-0059c45dfa78d6-c383f64-1049088-16f9edc474895%22%7D; _gscu_564121711=80128103kc5dx617; X-LB=1.1.44.637df82f; _va_ref=%5B%22%22%2C%22%22%2C1580462724%2C%22https%3A%2F%2Fwww.baidu.com%2Flink%3Furl%3DM-f5ankfbAnnYIH43aTQ0bvcFij9-hVxwm64pCc6rhCu5DYwg6xEVis-OVjqGinh%26wd%3D%26eqid%3Dd6b151bf000cfb36000000025e1c5d84%22%5D; _va_ses=*; route=74cee48a71a9ef78636a55b3fa493f67; _va_id=b24752d801da28d7.1578917255.10.1580462811.1580450943.',
}
}
# 需要重写start_requests方法
def start_requests(self):
# 网页里ajax链接
url = "http://www.beijing.gov.cn/hudong/hdjl/com.web.search.mailList.mailList.biz.ext"
# 所有请求集合
requests = []
for i in range(0, 33750,1000):
random_random = random.random()
# 封装post请求体参数
my_data = {'PageCond/begin': i, 'PageCond/length': 1000, 'PageCond/isCount': 'true', 'keywords': '',
'orgids': '', 'startDate': '', 'endDate': '', 'letterType': '', 'letterStatue': ''}
# 模拟ajax发送post请求
request = scrapy.http.Request(url, method='POST',
callback=self.parse_model,
body=json.dumps(my_data),
encoding='utf-8')
requests.append(request)
return requests
def parse_model(self, response):
# 可以利用json库解析返回来得数据
jsonBody = json.loads(response.body)
print(jsonBody)
size = jsonBody['PageCond']['size']
data = jsonBody['mailList']
listdata = {}
for i in range(size):
print(i)
listdata['letter_type'] = data[i]['letter_type']
listdata['original_id'] = data[i]['original_id']
listdata['catalog_id'] =str(data[i]['catalog_id'])
listdata['letter_title'] = data[i]['letter_title']
listdata['create_date'] = data[i]['create_date']
listdata['org_id'] = data[i]['org_id']
listdata['letter_status'] = data[i]['letter_status']
yield listdata
print(listdata)
item.py
class DataItem(scrapy.Item):
letter_type=scrapy.Field()
original_id = scrapy.Field()
catalog_id = scrapy.Field()
letter_title = scrapy.Field()
create_date = scrapy.Field()
org_id = scrapy.Field()
letter_status = scrapy.Field()
setting.py
BOT_NAME = 'xinjian'
SPIDER_MODULES = ['freebuf.freebuf.spiders']
NEWSPIDER_MODULE = 'freebuf.freebuf.spiders.testSpider'
之后通过在命令行进入项目目录输入scrapy crawl xinjian-o data.csv 来运行项目其中-o表示保存文件
附最后截图:
遇到的问题:
目标服务器连接被拒绝之类的······
原因:请求此时过多,我之前是六个一请求,
解决方案:将请求的长度变大每次请求1000个,减少请求次数