Python HTTP GET。 “错误的请求”

时间:2016-03-23 16:16:07

标签: python html http get

我正在尝试编写一个代码,用于从用户输入的网站获取html代码。我需要在不使用urllib或其他类似库的情况下编写它。

 from socket import *


url = (input("Please enter url: "))
host=gethostbyname(url)

clientSocket = socket(AF_INET, SOCK_STREAM)
clientSocket.connect((host,80))

clientSocket.send(("GET " + host + "HTTP/1.1\n\n").encode("UTF-8"))

file = clientSocket.recv(1024)
print("The html code: ", file.decode("UTF-8"))
clientSocket.close()

代码运行正常。但是,当我输入诸如“www.stackoverflow.com”之类的网站时,我收到了来自主持人的“错误请求”回复:

The html code:  HTTP/1.1 400 Bad Request

Date: Wed, 23 Mar 2016 16:14:27 GMT

Content-Type: text/html

Content-Length: 177

Connection: close

Server: -nginx

CF-RAY: -



<html>

<head><title>400 Bad Request</title></head>

<body bgcolor="white">

<center><h1>400 Bad Request</h1></center>

<hr><center>cloudflare-nginx</center>

</body>

</html>

为了从服务器获取实际的html代码,正确的请求是什么?谢谢

2 个答案:

答案 0 :(得分:1)

主机名不是网址。由于您使用package com.example.country; import android.content.Intent; import android.os.Bundle; import android.support.v7.app.AppCompatActivity; import android.support.v7.widget.Toolbar; import android.text.Editable; import android.text.TextWatcher; import android.view.View; import android.widget.AdapterView; import android.widget.ArrayAdapter; import android.widget.Button; import android.widget.EditText; import android.widget.ImageView; import android.widget.Spinner; import android.widget.Toast; import java.util.Arrays; import java.util.Collections; import java.util.Comparator; import java.util.List; public class Select extends AppCompatActivity { ImageView flagChoiceView; Spinner spinnerCountry; ArrayAdapter<CharSequence> adapter; public static Button next2; //Declaring all objects of type Country List<Country> countries = Arrays.asList( new Country("Austria", R.drawable.austriaflag), new Country("Belgium", R.drawable.belgiumflag), new Country("Denmark", R.drawable.denmarkflag), new Country("England", R.drawable.englandflag), new Country("France", R.drawable.franceflag), new Country("Germany", R.drawable.germanflag), new Country("Ireland", R.drawable.irelandflag), new Country("Italy", R.drawable.italyflag), new Country("Luxembourg", R.drawable.luxembourgeflag), new Country("Portugal", R.drawable.portugalflag), new Country("Spain", R.drawable.spainflag), new Country("Sweden", R.drawable.swedenflag), new Country("Switzerland", R.drawable.switzerlandflag), new Country("Wales", R.drawable.walesflag) ); @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_select); Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar); setSupportActionBar(toolbar); afterSecondClick(); //Setting protocols for entering values into the text field final TextWatcher numberInput = new TextWatcher() { @Override public void beforeTextChanged(CharSequence s, int start, int count, int after) { } @Override public void onTextChanged(CharSequence s, int start, int before, int count) { try { countries.get(spinnerCountry.getSelectedItemPosition()).setFrequency(Integer.parseInt(s.toString())); } catch (NumberFormatException e) { Toast.makeText(getParent(), s + " is not a number", Toast.LENGTH_SHORT).show(); } } @Override public void afterTextChanged(Editable s) { } }; //Creating a listener for the input field EditText inputFrequency = (EditText) findViewById(R.id.inputFrequency); inputFrequency.addTextChangedListener(numberInput); //sortFunction(countryList); spinnerCountry = (Spinner) findViewById(R.id.dropdown); adapter = ArrayAdapter.createFromResource(this, R.array.country_list, android.R.layout.simple_spinner_item); adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); spinnerCountry.setAdapter(adapter); spinnerCountry.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() { @Override public void onItemSelected(AdapterView<?> parent, View view, final int position, long id) { flagChoiceView = (ImageView) findViewById(R.id.flagChoice); flagChoiceView.setImageResource(countries.get(position).getFlag()); } @Override public void onNothingSelected(AdapterView<?> parent) { } }); } //Linking the second activity to the third with a button click public void afterSecondClick() { next2 = (Button) findViewById(R.id.button); next2.setOnClickListener( new View.OnClickListener() { @Override public void onClick(View v) { Collections.sort(countries, Country.sortByFrequency()); Intent proceedAgain = new Intent("com.example.Country.Results"); proceedAgain.putExtra("firstCountry", countries.get(countries.size() - 1).getName()); proceedAgain.putExtra("secondCountry", countries.get(countries.size() - 2).getName()); proceedAgain.putExtra("thirdCountry", countries.get(countries.size() - 3).getName()); proceedAgain.putExtra("firstFrequency", countries.get(countries.size() - 1).getFrequency()); proceedAgain.putExtra("secondFrequency", countries.get(countries.size() - 2).getFrequency()); proceedAgain.putExtra("thirdFrequency", countries.get(countries.size() - 3).getFrequency()); startActivity(proceedAgain); EditText inputFrequency = (EditText) findViewById(R.id.inputFrequency); inputFrequency.setText(""); } } ); } //Declaring a new inner class known as Country private static class Country { private final String name; private int frequency; private final int flag; public Country(String Name, int flag) { this.name = Name; this.frequency = 0; this.flag = flag; } public void setFrequency(int freq) { this.frequency = freq; } public int getFrequency() { return frequency; } public String getName() { return name; } public int getFlag() { return flag; } public static Comparator<Country> sortByFrequency() { return new Comparator<Country>() { @Override public int compare(Country lhs, Country rhs) { return Integer.compare(lhs.getFrequency(), rhs.getFrequency()); } }; } } ,因此您的脚本似乎仅提示输入主机名。 gethostbyname()请求期望查看其第一个参数的URI。您还需要使用换行符发送回车符,并且您需要两个终止GET请求。你应该这样:

GET

此外,如果您只想下载URL,请使用像clientSocket.send(("GET / HTTP/1.1\r\n\r\n").encode("UTF-8")) 这样的库来处理所有HTTP协议详细信息。例如:

urllib2

答案 1 :(得分:0)

你不是在说HTTP / 1.1,但是你在第一行就是这样说的。

首先,GET之后的令牌必须是服务器上的绝对路径;因此从/开始。

其次,HTTP / 1.1请求必须包含Host:标头。

第三,您的简单客户端应该说Connection: close,因为它不处理分块连接。

使用以下脚本可能会取得更大的成功:

from socket import *

host = gethostbyname('stackoverflow.com')
clientSocket = socket(AF_INET, SOCK_STREAM)
clientSocket.connect((host,80))
clientSocket.send((
    "GET / HTTP/1.1\r\n"
    "Host: stackoverflow.com\r\n"
    "Connection: close\r\n\r\n").encode('utf-8'))

file = clientSocket.recv(1024)
print("The html code: ", file.decode("UTF-8"))
clientSocket.close()